123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869[@@@ifge4.12]includeAtomic[@@@else_]openStdlib(* for == *)type'at={mutablex:'a}let[@inline]makex={x}let[@inline]get{x}=xlet[@inline]setrx=r.x<-xlet[@inlinenever]exchangerx=(* atomic *)lety=r.xinr.x<-x;(* atomic *)ylet[@inlinenever]compare_and_setrseenv=(* atomic *)ifr.x==seen then(r.x<-v;(* atomic *)true)elsefalselet[@inlinenever]fetch_and_addrx=(* atomic *)letv=r.xinr.x<-x+r.x;(* atomic *)vlet[@inline never]incrr=(* atomic *)r.x<-1+r.x(* atomic *)let[@inlinenever]decrr=(* atomic *)r.x<-r.x-1(* atomic *)[@@@endif](** Update loop with a compare-and-swap, and some basic backoff behavior.
[update_cas atomic f] is, in essence,
[let res, x = f !atomic in atomic := x; res]
done atomically. [f] might be called multiple times and must be as cheap
as possible.
@since 3.17 *)letupdate_cas(typeres)(self:'at)(f:'a->res*'a):res=letexceptionRetofresinletbackoff=ref1intrywhiletruedoletold_val=getselfinletres,new_val=fold_valinifcompare_and_setselfold_valnew_valthenraise_notrace(Retres);Containers_domain.relax_loop!backoff;backoff:=min128(2*!backoff)done;assertfalsewithRetr->r