123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118(** {1 Semaphores} *)typet={mutablen:int;mutex:Mutex.t;cond:Condition.t;}letcreaten=ifn<=0theninvalid_arg"Semaphore.create";{n;mutex=Mutex.create();cond=Condition.create();}letgett=t.n(* assume [t.mutex] locked, try to acquire [t] *)letacquire_once_locked_mt=whilet.n<mdoCondition.waitt.condt.mutex;done;assert(t.n>=m);t.n<-t.n-m;Condition.broadcastt.cond;Mutex.unlockt.mutexletacquiremt=Mutex.lockt.mutex;acquire_once_locked_mt(* assume [t.mutex] locked, try to release [t] *)letrelease_once_locked_mt=t.n<-t.n+m;Condition.broadcastt.cond;Mutex.unlockt.mutexletreleasemt=Mutex.lockt.mutex;release_once_locked_mt;()(*$R
let s = create 1 in
let r = CCLock.create false in
let _ = Thread.create (fun s -> acquire 5 s; CCLock.set r true) s in
Thread.yield ();
assert_equal false (CCLock.get r);
release 4 s;
Thread.delay 0.2;
assert_equal true (CCLock.get r);
assert_equal 0 (get s)
*)letwith_acquire~nt~f=acquirent;tryletx=f()inreleasent;xwithe->releasent;raisee(*$R
let s = create 5 in
let n = CCLock.create 0 in
let a = Array.init 100 (fun i ->
Thread.create (fun _ ->
for _i = 1 to 100 do
with_acquire ~n:(1 + (i mod 5)) s
~f:(fun () -> Thread.yield(); CCLock.incr n)
done)
())
in
Array.iter Thread.join a;
assert_equal ~printer:CCInt.to_string 5 (get s);
assert_equal ~printer:CCInt.to_string 10_000 (CCLock.get n)
*)letwait_until_at_least~nt~f=Mutex.lockt.mutex;whilet.n<ndoCondition.waitt.condt.mutex;done;assert(t.n>=n);Mutex.unlockt.mutex;f()(*$R
let output s = () in
let s = create 2 in
let res = CCLock.create false in
let id = Thread.create
(fun () ->
output "start";
wait_until_at_least ~n:5 s
~f:(fun () ->
assert (get s >= 5);
output "modify now";
CCLock.set res true)
) ()
in
output "launched thread";
Thread.yield();
assert_bool "start" (not (CCLock.get res));
output "release 2";
release 2 s;
Thread.yield();
assert_bool "after release 2" (not (CCLock.get res));
output "release 1";
release 1 s;
(* should work now *)
Thread.delay 0.2;
Thread.join id;
output "check";
assert_bool "after release 1" (CCLock.get res)
*)