123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899moduletypePrim=sig@@portableopenImporttypet:valuemodcontendedforkablenon_floatportableunyieldingvalcreate:?padded:bool@local->unit@local->t(* *)valacquire:Await.t@local->t@local->unitvalacquire_or_cancel:Await.t@local->Cancellation.t@local->t@local->unitOr_canceled.tvaltry_acquire:t@local->bool(* *)valrelease:t@local->unitvalrelease_and_reraise:('r:value_or_null).exn->t@local->'r@portableunique(* *)valpoison:t@local->unitvalpoison_and_reraise:('r:value_or_null).exn->t@local->'r@portableunique(* *)valis_poisoned:t@local->boolvalis_locked:t@local->boolmoduleFor_testing:sigvalis_exclusive:t@local->boolvallength:t@local->intendendmoduletypeSync=sig@@portableopenAwait_kernelmoduleCapsule:=Capsule.Prim(** Mutexes that can only be held for a bounded period of time *)(** [k t] is the type of a mutex protecting the contents of the [k] capsule which can
only be held for a bounded period of time. *)type'kt:valuemodcontendedforkablenon_floatportableunyielding(** {1 Creating a mutex} *)(** [create k] creates a new mutex for the capsule ['k] associated with [k], consuming
the key itself.
The optional [padded] argument specifies whether to pad the data structure to avoid
false sharing. See {!Atomic.make} for a longer explanation. *)valcreate:?padded:bool@local->'kCapsule.Key.t@unique->'kt(** {1 Executing critical sections} *)(** {2 With uncontended [Access]} *)[%%template:[@@@mode.defaultl=(local,global)](** [with_access s t ~f] acquires [t], runs [f] within the associated capsule, then
releases [t]. If [t] is locked then uses [s] to wait until it is unlocked. The
[Sync.t] is passed to [f] to allow further use of synchronization primitives.
@raise Poisoned if [t] cannot be acquired because it is poisoned. *)valwith_access:('a:value_or_null)'k.Sync.t@local->'kt@local->f:(Sync.t@local->'kCapsule.Access.t->'a@contendedlonceportableunique)@localonceportableunyielding->'a@contendedlonceportableunique(** [try_with_access t ~f] is like {!with_access}, but returns [Would_block] if [t] is
currently locked. *)valtry_with_access:('a:value_or_null)'k.'kt@local->f:('kCapsule.Access.t->'a@contendedlonceportableunique)@localonceportableunyielding->'aOr_would_block.t@contendedlonceportableunique(** [with_access_poisoning s t ~f] acquires [t], runs [f] within the associated capsule,
then releases [t]. If [t] is locked then uses [s] to wait until it is unlocked. The
[Sync.t] is passed to [f] to allow further use of synchronization primitives.
Poisons [t] if [f] raises an uncaught exception.
@raise Poisoned if [t] cannot be acquired because it is poisoned. *)valwith_access_poisoning:('a:value_or_null)'k.Sync.t@local->'kt@local->f:(Sync.t@local->'kCapsule.Access.t->'a@contendedlonceportableunique)@localonceportableunyielding->'a@contendedlonceportableunique(** [try_with_access_poisoning t ~f] is like {!with_access_poisoning}, but returns
[Would_block] if [t] is currently locked. *)valtry_with_access_poisoning:('a:value_or_null)'k.'kt@local->f:('kCapsule.Access.t->'a@contendedlonceportableunique)@localonceportableunyielding->'aOr_would_block.t@contendedlonceportableunique(** [with_access_or_cancel s c t f] is [Completed (with_access s t f)] if [c] is not
canceled, otherwise it is [Canceled]. *)valwith_access_or_cancel:('a:value_or_null)'k.Sync.t@local->Cancellation.t@local->'kt@local->f:(Sync.t@local->'kCapsule.Access.t->'a@contendedlonceportableunique)@localonceportableunyielding->'aOr_canceled.t@contendedlonceportableunique(** [with_access_or_cancel_poisoning s c t f] is
[Completed (with_access_poisoning s t f)] if [c] is not canceled, otherwise it is
[Canceled].
Poisons [t] if [f] raises an uncaught exception. *)valwith_access_or_cancel_poisoning:('a:value_or_null)'k.Sync.t@local->Cancellation.t@local->'kt@local->f:(Sync.t@local->'kCapsule.Access.t->'a@contendedlonceportableunique)@localonceportableunyielding->'aOr_canceled.t@contendedlonceportableunique](** {2 With a local [Password]} *)(** [with_password s t f] acquires [t], runs [f] with permission to access the
associated capsule, then releases [t]. If [t] is locked then uses [s] to wait until
it is unlocked. The [Sync.t] is passed to [f] to allow further use of
synchronization primitives.
@raise Poisoned if [t] cannot be acquired because it is poisoned. *)valwith_password:('a:value_or_null)'k.Sync.t@local->'kt@local->f:(Sync.t@local->'kCapsule.Password.t@local->'a@unique)@localonceunyielding->'a@unique(** [try_with_password t ~f] is like {!with_password}, but returns [Would_block] if [t]
is currently locked. *)valtry_with_password:('a:value_or_null)'k.'kt@local->f:('kCapsule.Password.t@local->'a@unique)@localonceunyielding->'aOr_would_block.t@unique(** [with_password_poisoning s t f] acquires [t], runs [f] with permission to access the
associated capsule, then releases [t]. If [t] is locked then uses [s] to wait until
it is unlocked. The [Sync.t] is passed to [f] to allow further use of
synchronization primitives.
Poisons [t] if [f] raises an exception.
@raise Poisoned if [t] cannot be acquired because it is poisoned. *)valwith_password_poisoning:('a:value_or_null)'k.Sync.t@local->'kt@local->f:(Sync.t@local->'kCapsule.Password.t@local->'a@unique)@localonceunyielding->'a@unique(** [try_with_password_poisoning t ~f] is like {!with_password_poisoning}, but returns
[Would_block] if [t] is currently locked. *)valtry_with_password_poisoning:('a:value_or_null)'k.'kt@local->f:('kCapsule.Password.t@local->'a@unique)@localonceunyielding->'aOr_would_block.t@unique(** [with_password_or_cancel s c t f] is [Completed (with_password s t f)] if [c] is not
canceled, otherwise it is [Canceled]. *)valwith_password_or_cancel:('a:value_or_null)'k.Sync.t@local->Cancellation.t@local->'kt@local->f:(Sync.t@local->'kCapsule.Password.t@local->'a@unique)@localonceunyielding->'aOr_canceled.t@unique(** [with_password_or_cancel_poisoning s c t f] is
[Completed (with_password_poisoning s t f)] if [c] is not canceled, otherwise it is
[Canceled].
Poisons [t] if [f] raises an exception. *)valwith_password_or_cancel_poisoning:('a:value_or_null)'k.Sync.t@local->Cancellation.t@local->'kt@local->f:(Sync.t@local->'kCapsule.Password.t@local->'a@unique)@localonceunyielding->'aOr_canceled.t@unique(** {2 With a unique [Key]} *)[%%template:[@@@mode.defaultl=(global,local)](** [with_key_poisoning s t ~f] locks [t] and runs [f], providing it a key for ['k]
uniquely. If the function raises without returning the key back, the mutex is
poisoned. If [t] is locked, then [with_key_poisoning] uses [s] to wait until it is
unlocked. The [Sync.t] is passed to [f] to allow further use of synchronization
primitives.
There is no non-poisoning version of this function, because you must return the key
back (to avoid leaking it via an exception).
@raise Poisoned if [t] cannot be acquired because it is poisoned. *)valwith_key_poisoning:('a:value_or_null)'k.Sync.t@local->'kt@local->f:(Sync.t@local->'kCapsule.Key.t@unique->#('a*'kCapsule.Key.t)@lonceunique)@localonceunyielding->'a@lonceunique(** [try_with_key t ~f] is like {!with_key}, but returns [Would_block] if [t] is
currently locked. *)valtry_with_key_poisoning:('a:value_or_null)'k.'kt@local->f:('kCapsule.Key.t@unique->#('a*'kCapsule.Key.t)@lonceunique)@localonceunyielding->'aOr_would_block.t@lonceunique(** [with_key_or_cancel_poisoning s c t ~f] is [Completed (with_key_poisoning s t ~f)]
if [c] is not canceled, otherwise it is [Canceled]. *)valwith_key_or_cancel_poisoning:('a:value_or_null)'k.Sync.t@local->Cancellation.t@local->'kt@local->f:(Sync.t@local->'kCapsule.Key.t@unique->#('a*'kCapsule.Key.t)@lonceunique)@localonceunyielding->'aOr_canceled.t@lonceunique](** {3 And waiting for a [Condition]} *)moduleCondition:Condition.Swithtype'klock:='kt(** @open *)[%%template:[@@@mode.defaultl=(global,local)](** [with_key_and_condition_wait_poisoning w t ~f] locks [t] and runs [f], providing it
with a key for ['k] uniquely and a ['k Condition.Wait.t] which provides the ability
to temporarily unlock [t] and wait on an associated ['k Condition.t]. Since waiting
on a condition variable can delay for an unbounded period of time, this requires an
[Await.t], even for a [Sync] mutex, but only passes a [Sync.t] to the callback. To
recover the original [Await.t] during the execution of [f], you can use
{!Condition.Wait.release_temporarily}.
The lock is only poisoned if [f] raises {i while the lock held}; if waiting on a
condition variable is terminated or if the callback passed to
{!Condition.Wait.release_temporarily} raises, the lock will not be poisoned.
@raise Poisoned if [t] cannot be acquired because it is poisoned.
@raise Terminated if [w] is terminated before the mutex is acquired. *)valwith_key_and_condition_wait_poisoning:('a:value_or_null)'k.Await.t@local->'kt@local->f:(Sync.t@local->'kCondition.Wait.t@local->'kCapsule.Key.t@unique->#('a*'kCapsule.Key.t)@lonceunique)@localonceunyielding->'a@lonceunique(** [with_key_and_condition_wait_or_cancel_poisoining w c t ~f] is
[Completed (with_key_and_condition_wait_poisoining w t ~f)] if [c] is not canceled,
otherwise it is [Canceled]. *)valwith_key_and_condition_wait_or_cancel_poisoning:('a:value_or_null)'k.Await.t@local->Cancellation.t@local->'kt@local->f:(Sync.t@local->'kCondition.Wait.t@local->'kCapsule.Key.t@unique->#('a*'kCapsule.Key.t)@lonceunique)@localonceunyielding->'aOr_canceled.t@lonceunique](** {3 And releasing temporarily} *)(** [release_temporarily s t k ~f] releases [t], runs [f] without the mutex, reacquires
[t] and returns the result of running [f] along with the [k].
To obtain a key to pass to [release_temporarily], use {!with_key} or similar
functions.
@raise Poisoned if [t] cannot be reacquired because it is poisoned. *)valrelease_temporarily:('a:value_or_null)'k.Sync.t@local->'kt@local->'kCapsule.Key.t@unique->f:(unit->'a@unique)@localonce->#('a*'kCapsule.Key.t)@unique(** [release_temporarily_or_cancel s c t k ~f] is
[Completed (release_temporarily s t k ~f)] if [c] is not canceled, otherwise it is
[Canceled]. *)valrelease_temporarily_or_cancel:('a:value_or_null).Sync.t@local->Cancellation.t@local->'kt@local->'kCapsule.Key.t@unique->f:(unit->'a@unique)@localonceunyielding->(#('a*'kCapsule.Key.t)Or_canceled.t[@kindvalue_or_null&void])@unique(** {3 And poisoning indefinitely} *)(** [poison t key] poisons the mutex associated with the [key]. *)valpoison:'kt@local->'kCapsule.Key.t@unique->'kCapsule.Key.t@unique(** {2 Indefinitely through poisoning} *)(** [acquire_and_poison s t] acquires [t] and then immediately poisons it, returning the
key to the protected capsule.
@raise Poisoned if [t] cannot be acquired because it is poisoned. *)valacquire_and_poison:Sync.t@local->'kt@local->'kCapsule.Key.t@unique(** [acquire_and_poison_or_cancel s c t] is [Completed (acquire_and_poison s t)] if [c]
is not canceled, otherwise it is [Canceled]. *)valacquire_and_poison_or_cancel:Sync.t@local->Cancellation.t@local->'kt@local->('kCapsule.Key.tOr_canceled.t[@kindvoid])@unique(** {1 Poisoning as a signal} *)(** [is_poisoned t] determines whether the mutex [t] is poisoned. *)valis_poisoned:'kt@local->bool(** [is_locked t] determines whether the mutex [t] is locked. *)valis_locked:'kt@local->bool(** [poison_unacquired t] poisons [t] without acquiring it. Does nothing if [t] is
already poisoned.
Note that this can render the capsule associated with [t] innaccessible, since it
potentially destroys the associated key. *)valpoison_unacquired:'kt@local->unit(**/**)moduleFor_testing:sig(** [is_exclusive t] determines whether the mutex [t] is locked. *)valis_exclusive:'kt@local->bool(** [length t] returns an upper bound on the length of the internal queue of awaiters
for testing purposes. *)vallength:'kt@local->intendendmoduletypeAwait=sig@@portableopenAwait_kernelmoduleCapsule:=Capsule.Prim(** Mutexes that can be held for an unbounded period of time *)(** [k t] is the type of a mutex protecting the contents of the [k] capsule, which can
be held for an unbounded period of time. *)type'kt:valuemodcontendedforkablenon_floatportableunyielding(** {1 Creating a mutex} *)(** [create k] creates a new mutex for the capsule ['k] associated with [k], consuming
the key itself.
The optional [padded] argument specifies whether to pad the data structure to avoid
false sharing. See {!Atomic.make} for a longer explanation. *)valcreate:?padded:bool@local->'kCapsule.Key.t@unique->'kt(** {1 Executing critical sections} *)(** {2 With uncontended [Access]} *)(** [with_access w t ~f] acquires [t], runs [f] within the associated capsule, then
releases [t]. If [t] is locked then uses [w] to wait until it is unlocked.
@raise Poisoned if [t] cannot be acquired because it is poisoned.
@raise Terminated if [w] is terminated before the mutex is acquired. *)valwith_access:('a:value_or_null)'k.Await.t@local->'kt@local->f:('kCapsule.Access.t->'a@contendedonceportableunique)@localonceportable->'a@contendedonceportableunique(** [try_with_access t ~f] is like {!with_access}, but returns [Would_block] if [t] is
currently locked. *)valtry_with_access:('a:value_or_null)'k.'kt@local->f:('kCapsule.Access.t->'a@contendedonceportableunique)@localonceportable->'aOr_would_block.t@contendedonceportableunique(** [with_access_poisoning w t ~f] acquires [t], runs [f] within the associated capsule,
then releases [t]. If [t] is locked then uses [w] to wait until it is unlocked.
Poisons [t] if [f] raises an uncaught exception.
@raise Poisoned if [t] cannot be acquired because it is poisoned.
@raise Terminated if [w] is terminated before the mutex is acquired. *)valwith_access_poisoning:('a:value_or_null)'k.Await.t@local->'kt@local->f:('kCapsule.Access.t->'a@contendedonceportableunique)@localonceportable->'a@contendedonceportableunique(** [try_with_access_poisoning t ~f] is like {!with_access_poisoning}, but returns
[Would_block] if [t] is currently locked. *)valtry_with_access_poisoning:('a:value_or_null)'k.'kt@local->f:('kCapsule.Access.t->'a@contendedonceportableunique)@localonceportable->'aOr_would_block.t@contendedonceportableunique(** [with_access_or_cancel w c t f] is [Completed (with_access w t f)] if [c] is not
canceled, otherwise it is [Canceled].
@raise Terminated if [w] is terminated, even if [c] is canceled. *)valwith_access_or_cancel:('a:value_or_null)'k.Await.t@local->Cancellation.t@local->'kt@local->f:('kCapsule.Access.t->'a@contendedonceportableunique)@localonceportable->'aOr_canceled.t@contendedonceportableunique(** [with_access_or_cancel_poisoning w c t f] is
[Completed (with_access_poisoning w t f)] if [c] is not canceled, otherwise it is
[Canceled].
Poisons [t] if [f] raises an uncaught exception.
@raise Terminated if [w] is terminated, even if [c] is canceled. *)valwith_access_or_cancel_poisoning:('a:value_or_null)'k.Await.t@local->Cancellation.t@local->'kt@local->f:('kCapsule.Access.t->'a@contendedonceportableunique)@localonceportable->'aOr_canceled.t@contendedonceportableunique(** {2 With a local [Password]} *)(** [with_password w t f] acquires [t], runs [f] with permission to access the
associated capsule, then releases [t]. If [t] is locked then uses [w] to wait until
it is unlocked.
@raise Poisoned if [t] cannot be acquired because it is poisoned.
@raise Terminated if [w] is terminated before the mutex is acquired. *)valwith_password:('a:value_or_null)'k.Await.t@local->'kt@local->f:('kCapsule.Password.t@local->'a@unique)@localonce->'a@unique(** [try_with_password t ~f] is like {!with_password}, but returns [Would_block] if [t]
is currently locked. *)valtry_with_password:('a:value_or_null)'k.'kt@local->f:('kCapsule.Password.t@local->'a@unique)@localonce->'aOr_would_block.t@unique(** [with_password_poisoning w t f] acquires [t], runs [f] with permission to access the
associated capsule, then releases [t]. If [t] is locked then uses [w] to wait until
it is unlocked.
Poisons [t] if [f] raises an exception.
@raise Poisoned if [t] cannot be acquired because it is poisoned.
@raise Terminated if [w] is terminated before the mutex is acquired. *)valwith_password_poisoning:('a:value_or_null)'k.Await.t@local->'kt@local->f:('kCapsule.Password.t@local->'a@unique)@localonce->'a@unique(** [try_with_password_poisoning t ~f] is like {!with_password_poisoning}, but returns
[Would_block] if [t] is currently locked. *)valtry_with_password_poisoning:('a:value_or_null)'k.'kt@local->f:('kCapsule.Password.t@local->'a@unique)@localonce->'aOr_would_block.t@unique(** [with_password_or_cancel w c t f] is [Completed (with_password w t f)] if [c] is not
canceled, otherwise it is [Canceled].
@raise Terminated if [w] is terminated, even if [c] is canceled. *)valwith_password_or_cancel:('a:value_or_null)'k.Await.t@local->Cancellation.t@local->'kt@local->f:('kCapsule.Password.t@local->'a@unique)@localonce->'aOr_canceled.t@unique(** [with_password_or_cancel_poisoning w c t f] is
[Completed (with_password_poisoning w t f)] if [c] is not canceled, otherwise it is
[Canceled].
Poisons [t] if [f] raises an exception.
@raise Terminated if [w] is terminated, even if [c] is canceled. *)valwith_password_or_cancel_poisoning:('a:value_or_null)'k.Await.t@local->Cancellation.t@local->'kt@local->f:('kCapsule.Password.t@local->'a@unique)@localonce->'aOr_canceled.t@unique(** {2 With a unique [Key]} *)[%%template:[@@@mode.defaultl=(global,local)](** [with_key_poisoning t ~f] locks [t] and runs [f], providing it a key for ['k]
uniquely. If the function raises without returning the key back, the mutex is
poisoned. If [t] is locked, then [with_key_poisoning] uses [w] to wait until it is
unlocked.
There is no non-poisoning version of this function, because you must return the key
back (to avoid leaking it via an exception).
@raise Poisoned if [t] cannot be acquired because it is poisoned.
@raise Terminated if [w] is terminated before the mutex is acquired. *)valwith_key_poisoning:('a:value_or_null)'k.Await.t@local->'kt@local->f:('kCapsule.Key.t@unique->#('a*'kCapsule.Key.t)@lonceunique)@localonce->'a@lonceunique(** [try_with_key t ~f] is like {!with_key}, but returns [Would_block] if [t] is
currently locked. *)valtry_with_key_poisoning:('a:value_or_null)'k.'kt@local->f:('kCapsule.Key.t@unique->#('a*'kCapsule.Key.t)@lonceunique)@localonce->'aOr_would_block.t@lonceunique(** [with_key_or_cancel_poisoning w c t ~f] is [Completed (with_key_poisoning w t ~f)]
if [c] is not canceled, otherwise it is [Canceled].
@raise Terminated if [w] is terminated, even if [c] is canceled. *)valwith_key_or_cancel_poisoning:('a:value_or_null)'k.Await.t@local->Cancellation.t@local->'kt@local->f:('kCapsule.Key.t@unique->#('a*'kCapsule.Key.t)@lonceunique)@localonce->'aOr_canceled.t@lonceunique](** {3 And waiting for a [Condition]} *)moduleCondition:Condition.Swithtype'klock:='kt(** @open *)[%%template:[@@@mode.defaultl=(global,local)](** [with_key_and_condition_wait_poisoning w t ~f] locks [t] and runs [f], providing it
with a key for ['k] uniquely and a ['k Condition.Wait.t] which provides the ability
to temporarily unlock [t] and wait on an associated ['k Condition.t].
The lock is only poisoned if [f] raises {i while the lock held}; if waiting on a
condition variable is terminated or if the callback passed to
{!Condition.Wait.release_temporarily} raises, the lock will not be poisoned.
@raise Poisoned if [t] cannot be acquired because it is poisoned.
@raise Terminated if [w] is terminated before the mutex is acquired. *)valwith_key_and_condition_wait_poisoning:('a:value_or_null)'k.Await.t@local->'kt@local->f:('kCondition.Wait.t@local->'kCapsule.Key.t@unique->#('a*'kCapsule.Key.t)@lonceunique)@localonce->'a@lonceunique(** [with_key_and_condition_wait_or_cancel_poisoining w c t ~f] is
[Completed (with_key_and_condition_wait_poisoining w t ~f)] if [c] is not canceled,
otherwise it is [Canceled]. *)valwith_key_and_condition_wait_or_cancel_poisoning:('a:value_or_null)'k.Await.t@local->Cancellation.t@local->'kt@local->f:('kCondition.Wait.t@local->'kCapsule.Key.t@unique->#('a*'kCapsule.Key.t)@lonceunique)@localonce->'aOr_canceled.t@lonceunique](** {3 And releasing temporarily} *)(** [release_temporarily w t k ~f] releases [t], runs [f] without the mutex, reacquires
[t] and returns the result of running [f] along with the [k].
To obtain a key to pass to [release_temporarily], use {!with_key} or similar
functions.
@raise Poisoned if [t] cannot be reacquired because it is poisoned.
@raise Terminated if [w] is terminated before the mutex is reacquired. *)valrelease_temporarily:('a:value_or_null)'k.Await.t@local->'kt@local->'kCapsule.Key.t@unique->f:(unit->'a@unique)@localonce->#('a*'kCapsule.Key.t)@unique(** [release_temporarily_or_cancel w c t k ~f] is
[Completed (release_temporarily w t k ~f)] if [c] is not canceled, otherwise it is
[Canceled]. *)valrelease_temporarily_or_cancel:('a:value_or_null).Await.t@local->Cancellation.t@local->'kt@local->'kCapsule.Key.t@unique->f:(unit->'a@unique)@localonce->(#('a*'kCapsule.Key.t)Or_canceled.t[@kindvalue_or_null&void])@unique(** {3 And poisoning indefinitely} *)(** [poison t key] poisons the mutex associated with the [key].
Note that poisoning a mutex does not signal waiters on associated {{!Condition}
condition variables}. *)valpoison:'kt@local->'kCapsule.Key.t@unique->'kCapsule.Key.t@unique(** {2 Indefinitely through poisoning} *)(** [acquire_and_poison w t] acquires [t] and then immediately poisons it, returning the
key to the protected capsule.
@raise Poisoned if [t] cannot be acquired because it is poisoned.
@raise Terminated if [w] is terminated before the mutex is acquired. *)valacquire_and_poison:Await.t@local->'kt@local->'kCapsule.Key.t@unique(** [acquire_and_poison_or_cancel w c t] is [Completed (acquire_and_poison w t)] if [c]
is not canceled, otherwise it is [Canceled]. *)valacquire_and_poison_or_cancel:Await.t@local->Cancellation.t@local->'kt@local->('kCapsule.Key.tOr_canceled.t[@kindvoid])@unique(** {2 With arbitrary dynamic scope} *)moduleGuard:sig(** ['k Mutex.Guard.t] represents a locked mutex. It morally contains a
{!Capsule.Key.t}, but also has a finalizer that poisons the mutex if it is garbage
collected without {!release} being called. *)type'kt:valuemodcontendedmanyportable(** [with_key t ~f] runs [f], providing it a key for ['k] uniquely. If the function
raises without returning the key back, the mutex is poisoned. *)valwith_key:('a:value_or_null)'k.'kt@unique->f:('kCapsule.Key.t@unique->#('a*'kCapsule.Key.t)@onceunique)@localonce->'a*'kt@onceunique(** [with_password g ~f] runs [f], providing it a password for ['k], and returns the
result of [f] together with the guard.
If [f] raises an exception, the mutex is poisoned, and the exception is reraised. *)valwith_password:'kt@unique->f:('kCapsule.Password.t@local->'a@unique)@localonce->'a*'kt@unique(** [access g ~f] runs [f], providing it access to the capsule ['k], and returns the
result of [f] together with the guard.
If [f] raises an exception, the mutex is poisoned, and the exception is reraised. *)valaccess:('a:value_or_null)'k.'kt@unique->f:('kCapsule.Access.t->'a@contendedonceportableunique)@localonceportable->'a*'kt@contendedonceportableunique(** [release guard] releases the mutex protected by [guard], consuming the guard. *)valrelease:'kt@unique->unit(** [poison guard] poisons the mutex protected by [guard], consuming the guard and
returning the key to the protected capsule.
Note that poisoning a mutex does not signal waiters on associated {{!Condition}
condition variables}. *)valpoison:'kt@unique->'kCapsule.Key.t@unique(** [is_poisoning guard] is [true] if [guard] will poison if its finalizer runs
without [release] being called. *)valis_poisoning:'kt@local->boolend(** [acquire w t] acquires [t] and returns a guard for the locked mutex. If [t] is
locked, then acquire uses [w] to wait until it is unlocked.
@raise Poisoned if [t] cannot be acquired because it is poisoned.
@raise Terminated if [w] is terminated before the mutex is acquired. *)valacquire:Await.t@local->'kt->'kGuard.t@unique(** [acquire_or_cancel w c t] is [Completed (acquire w t)] if [c] is not canceled,
otherwise it is [Canceled]. *)valacquire_or_cancel:Await.t@local->Cancellation.t@local->'kt->'kGuard.tOr_canceled.t@unique(** [try_acquire t] is like {!acquire}, but returns [Would_block] if [t] is currently
locked. *)valtry_acquire:'kt->'kGuard.tOr_would_block.t@unique(** {1 Poisoning as a signal} *)(** [is_poisoned t] determines whether the mutex [t] is poisoned. *)valis_poisoned:'kt@local->bool(** [is_locked t] determines whether the mutex [t] is locked. *)valis_locked:'kt@local->bool(** [poison_unacquired t] poisons [t] without acquiring it. Does nothing if [t] is
already poisoned.
Note that this can render the capsule associated with [t] innaccessible, since it
potentially destroys the associated key.
Note that poisoning a mutex does not signal waiters on associated {{!Condition}
condition variables}. *)valpoison_unacquired:'kt@local->unit(**/**)moduleFor_testing:sig(** [is_exclusive t] determines whether the mutex [t] is locked. *)valis_exclusive:'kt@local->bool(** [length t] returns an upper bound on the length of the internal queue of awaiters
for testing purposes. *)vallength:'kt@local->intendendmoduletypeMutex_common=sig@@portablemoduleMake_sync(Prim:Prim):Syncwithtype'kt=Prim.tmoduleMake_await(Prim:Prim):Awaitwithtype'kt=Prim.tendmoduletypeWith_state=sig@@portable(** Here is an example of a counter protected by a mutex embedded within an atomic
location:
{[
module Mutex = Await.Sync.Mutex
type t =
| T :
{ mutable mutex : 'k Mutex.Loc.State.t [@atomic]
; state : (int ref, 'k) Capsule.Data.t
}
-> t
let make (value : int) =
let (P key) = Capsule.Prim.create () in
T
{ mutex = Mutex.Loc.make key
; state = Capsule.Data.create (fun () -> ref value)
}
;;
let fetch_and_add sync (T t) delta =
Mutex.Loc.with_access sync [%atomic.loc t.mutex] ~f:(fun _ access : int ->
let counter = Capsule.Data.unwrap ~access t.state in
let value = !counter in
counter := value + delta;
value)
[@nontail]
;;
]}
Note the use of [[@atomic]] to specify an atomic location and [[%atomic.loc _]] to
get a reference to the atomic location. *)moduleState:sig(** Internal state of a mutex location. *)(** ['k t] represents the state of a mutex location protecting the key to the capsule
[k]. *)type'kt:immediateendendmoduletypeSync_loc=sig@@portableincludeWith_state(** @inline *)includeSyncwithtype'kt='kState.tAtomic.Loc.t(** @inline *)(** {1 Initializing a mutex embedded within an atomic location} *)(** [make key] computes the initial state for a mutex location. *)valmake:'kCapsule.Prim.Key.t@unique->'kState.tendmoduletypeAwait_loc=sig@@portableincludeWith_state(** @inline *)includeAwaitwithtype'kt='kState.tAtomic.Loc.t(** @inline *)(** {1 Initializing a mutex embedded within an atomic location} *)(** [make key] computes the initial state for a mutex location. *)valmake:'kCapsule.Prim.Key.t@unique->'kState.tendmoduletypeMutex=sig@@portablemoduleSync:sig(** A poisonable mutual exclusion lock. *)(** {1 Freestanding mutex} *)includeSync(** @inline *)(** {1 Mutex embedded within an atomic location} *)(** A poisonable single word mutual exclusion lock embedded within an atomic location. *)moduleLoc:Sync_locendmoduleAwait:sig(** A poisonable mutual exclusion lock. *)(** {1 Freestanding mutex} *)includeAwait(** @inline *)(** {1 Mutex embedded within an atomic location} *)(** A poisonable single word mutual exclusion lock embedded within an atomic location. *)moduleLoc:Await_locendend