Module Await.MutexSource

A poisonable mutual exclusion lock.

Freestanding mutex

Mutexes that can be held for an unbounded period of time

Sourcetype 'k t : value mod contended forkable non_float portable unyielding

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.

Creating a mutex

Sourceval create : ?padded:bool @ local -> 'k Capsule.Prim.Key.t @ unique -> 'k t @@ portable

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.

Executing critical sections

With uncontended Access

Sourceval with_access : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> 'k t @ local -> f: ('k Capsule.Prim.Access.t -> 'a @ unique once portable contended) @ local once portable -> 'a @ unique once portable contended @@ portable

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.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Terminated

    if w is terminated before the mutex is acquired.

Sourceval try_with_access : ('a : value_or_null) 'k. 'k t @ local -> f: ('k Capsule.Prim.Access.t -> 'a @ unique once portable contended) @ local once portable -> 'a Await_kernel.Or_would_block.t @ unique once portable contended @@ portable

try_with_access t ~f is like with_access, but returns Would_block if t is currently locked.

Sourceval with_access_poisoning : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> 'k t @ local -> f: ('k Capsule.Prim.Access.t -> 'a @ unique once portable contended) @ local once portable -> 'a @ unique once portable contended @@ portable

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.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Terminated

    if w is terminated before the mutex is acquired.

Sourceval try_with_access_poisoning : ('a : value_or_null) 'k. 'k t @ local -> f: ('k Capsule.Prim.Access.t -> 'a @ unique once portable contended) @ local once portable -> 'a Await_kernel.Or_would_block.t @ unique once portable contended @@ portable

try_with_access_poisoning t ~f is like with_access_poisoning, but returns Would_block if t is currently locked.

Sourceval with_access_or_cancel : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f: ('k Capsule.Prim.Access.t -> 'a @ unique once portable contended) @ local once portable -> 'a Await_kernel.Or_canceled.t @ unique once portable contended @@ portable

with_access_or_cancel w c t f is Completed (with_access w t f) if c is not canceled, otherwise it is Canceled.

  • raises Terminated

    if w is terminated, even if c is canceled.

Sourceval with_access_or_cancel_poisoning : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f: ('k Capsule.Prim.Access.t -> 'a @ unique once portable contended) @ local once portable -> 'a Await_kernel.Or_canceled.t @ unique once portable contended @@ portable

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.

  • raises Terminated

    if w is terminated, even if c is canceled.

With a local Password

Sourceval with_password : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> 'k t @ local -> f:('k Capsule.Prim.Password.t @ local -> 'a @ unique) @ local once -> 'a @ unique @@ portable

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.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Terminated

    if w is terminated before the mutex is acquired.

Sourceval try_with_password : ('a : value_or_null) 'k. 'k t @ local -> f:('k Capsule.Prim.Password.t @ local -> 'a @ unique) @ local once -> 'a Await_kernel.Or_would_block.t @ unique @@ portable

try_with_password t ~f is like with_password, but returns Would_block if t is currently locked.

Sourceval with_password_poisoning : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> 'k t @ local -> f:('k Capsule.Prim.Password.t @ local -> 'a @ unique) @ local once -> 'a @ unique @@ portable

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.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Terminated

    if w is terminated before the mutex is acquired.

Sourceval try_with_password_poisoning : ('a : value_or_null) 'k. 'k t @ local -> f:('k Capsule.Prim.Password.t @ local -> 'a @ unique) @ local once -> 'a Await_kernel.Or_would_block.t @ unique @@ portable

try_with_password_poisoning t ~f is like with_password_poisoning, but returns Would_block if t is currently locked.

Sourceval with_password_or_cancel : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f:('k Capsule.Prim.Password.t @ local -> 'a @ unique) @ local once -> 'a Await_kernel.Or_canceled.t @ unique @@ portable

with_password_or_cancel w c t f is Completed (with_password w t f) if c is not canceled, otherwise it is Canceled.

  • raises Terminated

    if w is terminated, even if c is canceled.

Sourceval with_password_or_cancel_poisoning : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f:('k Capsule.Prim.Password.t @ local -> 'a @ unique) @ local once -> 'a Await_kernel.Or_canceled.t @ unique @@ portable

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.

  • raises Terminated

    if w is terminated, even if c is canceled.

With a unique Key

Sourceval with_key_poisoning : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> 'k t @ local -> f: ('k Capsule.Prim.Key.t @ unique -> #('a * 'k Capsule.Prim.Key.t) @ unique once) @ local once -> 'a @ unique once @@ portable

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).

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Terminated

    if w is terminated before the mutex is acquired.

Sourceval try_with_key_poisoning : ('a : value_or_null) 'k. 'k t @ local -> f: ('k Capsule.Prim.Key.t @ unique -> #('a * 'k Capsule.Prim.Key.t) @ unique once) @ local once -> 'a Await_kernel.Or_would_block.t @ unique once @@ portable

try_with_key t ~f is like with_key, but returns Would_block if t is currently locked.

Sourceval with_key_or_cancel_poisoning : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f: ('k Capsule.Prim.Key.t @ unique -> #('a * 'k Capsule.Prim.Key.t) @ unique once) @ local once -> 'a Await_kernel.Or_canceled.t @ unique once @@ portable

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.

  • raises Terminated

    if w is terminated, even if c is canceled.

And waiting for a Condition
Sourcemodule Condition : sig ... end

Condition variable for waiting for changes to state protected by a lock.

Sourceval with_key_and_condition_wait_poisoning : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> 'k t @ local -> f: ('k Condition.Wait.t @ local -> ('k Capsule.Prim.Key.t @ unique -> #('a * 'k Capsule.Prim.Key.t) @ unique once) @ local once) @ local once -> 'a @ unique once @@ portable

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 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.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Terminated

    if w is terminated before the mutex is acquired.

Sourceval with_key_and_condition_wait_or_cancel_poisoning : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f: ('k Condition.Wait.t @ local -> ('k Capsule.Prim.Key.t @ unique -> #('a * 'k Capsule.Prim.Key.t) @ unique once) @ local once) @ local once -> 'a Await_kernel.Or_canceled.t @ unique once @@ portable

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.

And releasing temporarily
Sourceval release_temporarily : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> 'k t @ local -> 'k Capsule.Prim.Key.t @ unique -> f:(unit -> 'a @ unique) @ local once -> #('a * 'k Capsule.Prim.Key.t) @ unique @@ portable

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.

  • raises Poisoned

    if t cannot be reacquired because it is poisoned.

  • raises Terminated

    if w is terminated before the mutex is reacquired.

Sourceval release_temporarily_or_cancel : ('a : value_or_null). Await_kernel.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> 'k Capsule.Prim.Key.t @ unique -> f:(unit -> 'a @ unique) @ local once -> #('a * 'k Capsule.Prim.Key.t) Await_kernel.Or_canceled.t__'value_or_null_void' @ unique @@ portable

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.

And poisoning indefinitely
Sourceval poison : 'k t @ local -> 'k Capsule.Prim.Key.t @ unique -> 'k Capsule.Prim.Key.t @ unique @@ portable

poison t key poisons the mutex associated with the key.

Note that poisoning a mutex does not signal waiters on associated condition variables.

Indefinitely through poisoning

Sourceval acquire_and_poison : Await_kernel.Await.t @ local -> 'k t @ local -> 'k Capsule.Prim.Key.t @ unique @@ portable

acquire_and_poison w t acquires t and then immediately poisons it, returning the key to the protected capsule.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Terminated

    if w is terminated before the mutex is acquired.

Sourceval acquire_and_poison_or_cancel : Await_kernel.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> 'k Capsule.Prim.Key.t Await_kernel.Or_canceled.t__void @ unique @@ portable

acquire_and_poison_or_cancel w c t is Completed (acquire_and_poison w t) if c is not canceled, otherwise it is Canceled.

With arbitrary dynamic scope

Sourcemodule Guard : sig ... end
Sourceval acquire : Await_kernel.Await.t @ local -> 'k t -> 'k Guard.t @ unique @@ portable

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.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Terminated

    if w is terminated before the mutex is acquired.

Sourceval acquire_or_cancel : Await_kernel.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t -> 'k Guard.t Await_kernel.Or_canceled.t @ unique @@ portable

acquire_or_cancel w c t is Completed (acquire w t) if c is not canceled, otherwise it is Canceled.

Sourceval try_acquire : 'k t -> 'k Guard.t Await_kernel.Or_would_block.t @ unique @@ portable

try_acquire t is like acquire, but returns Would_block if t is currently locked.

Poisoning as a signal

Sourceval is_poisoned : 'k t @ local -> bool @@ portable

is_poisoned t determines whether the mutex t is poisoned.

Sourceval is_locked : 'k t @ local -> bool @@ portable

is_locked t determines whether the mutex t is locked.

Sourceval poison_unacquired : 'k t @ local -> unit @@ portable

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 variables.

Mutex embedded within an atomic location

A poisonable single word mutual exclusion lock embedded within an atomic location.

Sourcemodule Loc : sig ... end

Here is an example of a counter protected by a mutex embedded within an atomic location: