Recitation 16
Concurrency: Condition Variables and Message Passing
Condition Module
For this module we refer to OCaml's condition module documentation.
The reader writer concurrency pattern
(taken from lec16.ml)
let data = ref 0
let n = ref 0
let m = Mutex.create ()
let c = Condition.create ()
let reader_incr () =
Mutex.lock m ; incr n ; Mutex.unlock m
let reader_decr () =
Mutex.lock m ; decr n ; Mutex.unlock m
let reader_signal_when_empty () =
Mutex.lock m ;
if !n=0 then Condition.signal c ;
Mutex.unlock m
let read i =
reader_incr () ;
print_string("Reader " ^ string_of_int(i)
^ " read data " ^ string_of_int(!data) ^ "\n");
Thread.delay (Random.float 1.5) ;
print_string("Reader " ^ string_of_int(i) ^ " has finished reading\n") ;
reader_decr () ;
reader_signal_when_empty ()
let reader i =
while true do
read i;
Thread.delay (Random.float 1.5)
done
let write () =
Mutex.lock m ;
while !n<>0 do Condition.wait c m done ;
print_string "The writer is writing\n" ; flush stdout ;
data := 1 ; Thread.delay (Random.float 1.) ; data := 0 ;
Mutex.unlock m
let writer () =
while true do write () ; Thread.delay (Random.float 1.5) done
let test_reader_writer () =
ignore (Thread.create writer () );
for i=0 to 3 do ignore(Thread.create reader i) done
Event Module
For this module we refer to OCaml's event module documentation.
An example using events
(taken from lec16.ml)
let c1 = Event.new_channel ()
let c2 = Event.new_channel ()
let r (c) =
let idr = string_of_int(Thread.id(Thread.self ()))
in print_string("Before rec in " ^ idr ^"\n");
let e = Event.receive c
in print_string("During rec in " ^ idr ^ "\n");
let v = Event.sync e
in
print_string("Recd " ^ v ^ " in " ^ idr ^ "\n")
let r2 (c1,c2) =
let idr = string_of_int(Thread.id(Thread.self ()))
in print_string("Before rec in " ^ idr ^"\n");
let e1 = Event.receive c1
and e2 = Event.receive c2
in print_string("During rec in " ^ idr ^ "\n ");
let v = Event.select [e1;e2]
in
print_string("Recd " ^ v ^ " in " ^ idr ^ "\n")
let s (c,m) =
let ids = string_of_int(Thread.id(Thread.self ()))
in print_string("Start of sender " ^ ids ^ "\n");
let e = Event.send c m
in
Event.sync e;
print_string("End of sender " ^ ids ^ "\n")
let test_channels() =
ignore(Thread.create r (c1));
ignore(Thread.create r (c1));
ignore(Thread.create s (c1,"hello1"));
Thread.delay 2.0;
ignore(Thread.create s (c1,"after delay"))
let test_channels2() =
ignore(Thread.create r2 (c1,c2));
ignore(Thread.create s (c2,"hello2"));
ignore(Thread.create s (c1,"hello1"));
Thread.delay 2.0;
ignore(Thread.create r2 (c1,c2))