# Fair (to both) readers and writers. # # Fair in the sense that as soon as a writer arrives (while database is # being read, say) then no more newly arriving readers are allowed to # start reading. Instead the newly arriving readers must wait until # after that writer has written. That writer will then sweep into # reading the database those readers that had to wait. # However a finishing writer will sweep into reading the # database ALL waiting readers, even those readers that arrived after # a writer that arrived after the current writer that is just finishing. # resource server import MPDanimator op Start_Read(int i ), End_Read(int i ) op Start_Write(int i ), End_Write(int i ) body server() write("readers and writers server is alive") int Readers = 0 int Writers = 0 int Waiting_Readers = 0 int Waiting_Writers = 0 sem OK_to_read = 0 sem OK_to_write = 0 sem mutex = 1 proc Start_Read(i) { P(mutex) if (Waiting_Writers == 0 and Writers == 0) { Readers++ write(" age=", age(), "reader", i, "has begun reading, Readers==", Readers) V(mutex) } else { Waiting_Readers++ write("age=", age(), "reader", i, "waiting to read, Waiting_Readers==", Waiting_Readers) V(mutex) P(OK_to_read) } # Move the reader to be inside the database. call A_stepjumpto(3000+i, 7000+i, 3, 100) } proc End_Read(i) { P(mutex) Readers-- write(" age=", age(), "reader", i, "finished reading, Readers=", Readers) if (Readers == 0 and Waiting_Writers > 0) { V(OK_to_write) Writers++ Waiting_Writers-- } V(mutex) # Move the reader back to its original position. # Change consumers's symbol to an outline black circle. call A_stepjumpto(3000+i, 5000+i, 3, 100) call A_fill(3000+i, "outline") call A_color(3000+i, "black") } proc Start_Write(i) { P(mutex) if (Readers == 0 and Writers == 0) { Writers++ write(" age=", age(), "WRITER", i, "has begun Writing, Writers==", Writers, "(better be 1)") V(mutex) } else { Waiting_Writers++ write("age=", age(), "WRITER", i, "waiting to Write, Waiting_Writers==", Waiting_Writers) V(mutex) P(OK_to_write) } # Move the writer to be inside the database. call A_stepjumpto(2000+i, 7000+i, 3, 100) } proc End_Write(i) { Writers-- write(" age=", age(), "WRITER", i, "has finished Writing, Writers=", Writers, "(better be 0)") # Move the writer back to its original position. # Change the writer's symbol to an outline black circle. call A_stepjumpto(2000+i, 4000+i, 3, 100) call A_fill(2000+i, "outline") call A_color(2000+i, "black") if (Waiting_Readers > 0) { write(" age=", age(), "cascading in", Waiting_Readers, "readers") while (Waiting_Readers > 0) { V(OK_to_read) Readers++ Waiting_Readers-- } } } end server