(* remember to compile with ocamlc -vmthread threads.cma lec9.ml with any other options between the -vmthread and the threads.cma *) open Thread open Event (* for CML *) module LockBased = (* module just to avoid name clashes below *) struct type acct = { lk : Mutex.t; bal : float ref; avail : float ref} let mkAcct () = {lk=Mutex.create(); bal=ref 0.0; avail=ref 0.0} let get a f = Mutex.lock a.lk; (if(!(a.avail) > f) then (a.bal := !(a.bal) -. f; a.avail := !(a.avail) -.f)); Mutex.unlock a.lk let put a f = Mutex.lock a.lk; a.bal := !(a.bal) +. f; a.avail := !(a.avail) +.(if f < 500. then f else 500.); Mutex.unlock a.lk end let sendNow ch a = sync (send ch a) (*block *) let recvNow ch = sync (receive ch) type action = Put of float | Get of float type acct = action channel * float channel let mkAcct () = let inCh = new_channel() in let outCh = new_channel() in let bal = ref 0.0 in (* state *) let rec loop () = (match recvNow inCh with (* blocks *) Put f -> bal := !bal +. f; | Get f -> bal := !bal -. f);(*allows overdraw*) sendNow outCh !bal; loop () in ignore(create loop ()); (inCh,outCh) let get acct f = let inCh,outCh = acct in sendNow inCh (Get f); recvNow outCh let put acct f = let inCh,outCh = acct in sendNow inCh (Put f); recvNow outCh let squares = new_channel() let rec loop i = sendNow squares (i*i); loop (i+1) let _ = create loop 1 let one = recvNow squares let four = recvNow squares let nine = recvNow squares let pr i = print_string (string_of_int i) let _ = pr one; pr four; pr nine let add in1 in2 out = let ans = sync(choose[ wrap (receive in1) (fun i -> sync (receive in2) + i); wrap (receive in2) (fun i -> sync (receive in1) + i)]) in sync (send out ans) let i1 = new_channel() let i2 = new_channel() let o = new_channel() let _ = create (add i1 i2) o let _ = sync (send i2 7) let _ = sync (send i1 9) let _ = pr (sync (receive o))