123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188(* This file is free software, part of containers. See file "license" for more details. *)(** {1 Utils around Mutex} *)type'at={mutex:Mutex.t;mutablecontent:'a;}type'alock='atletcreatecontent={mutex=Mutex.create();content;}letwith_locklf=Mutex.lockl.mutex;tryletx=fl.contentinMutex.unlockl.mutex;xwithe->Mutex.unlockl.mutex;raisee(*$R
let l = create 0 in
let try_incr l =
update l (fun x -> Thread.yield(); x+1)
in
for i = 1 to 10 do ignore (Thread.create try_incr l) done;
Thread.delay 0.10 ;
assert_equal 10 (get l)
*)lettry_with_locklf=ifMutex.try_lockl.mutexthentryletx=fl.contentinMutex.unlockl.mutex;Somexwithe->Mutex.unlockl.mutex;raiseeelseNonemoduleLockRef=structtype'at='alockletgett=t.contentletsettx=t.content<-xletupdatetf=t.content<-ft.contentendletwith_lock_as_refl~f=Mutex.lockl.mutex;tryletx=flinMutex.unlockl.mutex;xwithe->Mutex.unlockl.mutex;raisee(*$R
let l = create 0 in
let test_it l =
with_lock_as_ref l
~f:(fun r ->
(* increment and decrement *)
for j = 0 to 100 do
let x = LockRef.get r in
LockRef.set r (x+10);
if j mod 5=0 then Thread.yield ();
let y = LockRef.get r in
LockRef.set r (y - 10);
done
)
in
for i = 1 to 100 do ignore (Thread.create test_it l) done;
Thread.delay 0.10;
assert_equal 0 (get l)
*)letmutexl=l.mutexletupdatelf=with_lockl(funx->l.content<-fx)(*$T
let l = create 5 in update l (fun x->x+1); get l = 6
*)letupdate_maplf=with_lockl(funx->letx',y=fxinl.content<-x';y)(*$T
let l = create 5 in update_map l (fun x->x+1, string_of_int x) = "5" && get l = 6
*)letgetl=Mutex.lockl.mutex;letx=l.contentinMutex.unlockl.mutex;xletsetlx=Mutex.lockl.mutex;l.content<-x;Mutex.unlockl.mutex(*$T
let l = create 0 in set l 4; get l = 4
let l = create 0 in set l 4; set l 5; get l = 5
*)letincrl=updatelStdlib.succletdecrl=updatelStdlib.pred(*$R
let l = create 0 in
let a = Array.init 100 (fun _ -> Thread.create (fun _ -> incr l) ()) in
Array.iter Thread.join a;
assert_equal ~printer:CCInt.to_string 100 (get l)
*)(*$T
let l = create 0 in incr l ; get l = 1
let l = create 0 in decr l ; get l = ~-1
*)letincr_then_getl=Mutex.lockl.mutex;l.content<-l.content+1;letx=l.contentinMutex.unlockl.mutex;xletget_then_incrl=Mutex.lockl.mutex;letx=l.contentinl.content<-l.content+1;Mutex.unlockl.mutex;xletdecr_then_getl=Mutex.lockl.mutex;l.content<-l.content-1;letx=l.contentinMutex.unlockl.mutex;xletget_then_decrl=Mutex.lockl.mutex;letx=l.contentinl.content<-l.content-1;Mutex.unlockl.mutex;x(*$T
let l = create 0 in 1 = incr_then_get l && 1 = get l
let l = create 0 in 0 = get_then_incr l && 1 = get l
let l = create 10 in 9 = decr_then_get l && 9 = get l
let l = create 10 in 10 = get_then_decr l && 9 = get l
*)letget_then_setl=Mutex.lockl.mutex;letx=l.contentinl.content<-true;Mutex.unlockl.mutex;xletget_then_clearl=Mutex.lockl.mutex;letx=l.contentinl.content<-false;Mutex.unlockl.mutex;x