Module Sync.MutexSource

A poisonable mutual exclusion lock.

Freestanding mutex

Mutexes that can only be held for a bounded 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 only be held for a bounded 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.Sync.t @ local -> 'k t @ local -> f: (Await_kernel.Sync.t @ local -> ('k Capsule.Prim.Access.t -> 'a @ unique once portable contended) @ local once) @ local once portable unyielding -> 'a @ unique once portable contended @@ portable

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.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

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 unyielding -> '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.Sync.t @ local -> 'k t @ local -> f: (Await_kernel.Sync.t @ local -> ('k Capsule.Prim.Access.t -> 'a @ unique once portable contended) @ local once) @ local once portable unyielding -> 'a @ unique once portable contended @@ portable

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.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

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 unyielding -> '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.Sync.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f: (Await_kernel.Sync.t @ local -> ('k Capsule.Prim.Access.t -> 'a @ unique once portable contended) @ local once) @ local once portable unyielding -> 'a Await_kernel.Or_canceled.t @ unique once portable contended @@ portable

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

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

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.

With a local Password

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

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.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

Sourceval try_with_password : ('a : value_or_null) 'k. 'k t @ local -> f:('k Capsule.Prim.Password.t @ local -> 'a @ unique) @ local once unyielding -> '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.Sync.t @ local -> 'k t @ local -> f: (Await_kernel.Sync.t @ local -> ('k Capsule.Prim.Password.t @ local -> 'a @ unique) @ local once) @ local once unyielding -> 'a @ unique @@ portable

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.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

Sourceval try_with_password_poisoning : ('a : value_or_null) 'k. 'k t @ local -> f:('k Capsule.Prim.Password.t @ local -> 'a @ unique) @ local once unyielding -> '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.Sync.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f: (Await_kernel.Sync.t @ local -> ('k Capsule.Prim.Password.t @ local -> 'a @ unique) @ local once) @ local once unyielding -> 'a Await_kernel.Or_canceled.t @ unique @@ portable

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

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

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.

With a unique Key

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

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

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

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 unyielding -> '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.Sync.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f: (Await_kernel.Sync.t @ local -> ('k Capsule.Prim.Key.t @ unique -> #('a * 'k Capsule.Prim.Key.t) @ unique once) @ local once) @ local once unyielding -> 'a Await_kernel.Or_canceled.t @ unique once @@ portable

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.

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: (Await_kernel.Sync.t @ local -> ('k Condition.Wait.t @ local -> ('k Capsule.Prim.Key.t @ unique -> #('a * 'k Capsule.Prim.Key.t) @ unique once) @ local once) @ local once) @ local once unyielding -> '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. 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 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: (Await_kernel.Sync.t @ local -> ('k Condition.Wait.t @ local -> ('k Capsule.Prim.Key.t @ unique -> #('a * 'k Capsule.Prim.Key.t) @ unique once) @ local once) @ local once) @ local once unyielding -> '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.Sync.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 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.

  • raises Poisoned

    if t cannot be reacquired because it is poisoned.

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

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.

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.

Indefinitely through poisoning

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

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

Sourceval acquire_and_poison_or_cancel : Await_kernel.Sync.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 s c t is Completed (acquire_and_poison s t) if c is not canceled, otherwise it is Canceled.

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.

Mutex embedded within an atomic location

Sourcemodule Loc : sig ... end

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