Module Sync.RwlockSource

A poisonable and freezable multiple readers, single writer lock that can only be held for a bounded period of time.

Sourcetype 'k t : value mod contended non_float portable

k t is the type of a read/write lock protecting the contents of the k capsule.

Creating a reader-writer lock

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

create k creates a new reader-writer lock 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 Access

Shared by readers

Sourceval with_access_shared : ('a : value_or_null) 'k. Await_kernel.Sync.t @ local -> 'k t @ local -> f: (Await_kernel.Sync.t @ local -> ('k Await_sync__.Rwlock.Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once) @ local once portable unyielding -> 'a @ unique once portable contended

with_access_shared w t ~f acquires t for reading, runs f with shared access to the associated capsule, then releases t. If t is locked for writing then uses w 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 with_access_shared_freezing : ('a : value_or_null) 'k. Await_kernel.Sync.t @ local -> 'k t @ local -> f: (Await_kernel.Sync.t @ local -> ('k Await_sync__.Rwlock.Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once) @ local once portable unyielding -> 'a @ unique once portable contended

with_access_shared_freezing w t ~f is with_access_shared w t ~f, but freezes t if f raises an uncaught exception.

Sourceval try_with_access_shared : ('a : value_or_null) 'k. 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once portable unyielding -> 'a Await_kernel.Or_would_block.t @ unique once portable contended

try_with_access_shared t ~f attempts to acquire t for reading without blocking. If successful, it runs f as with_access_shared would, but without taking a Sync.t because no waiting is needed. Otherwise, it is Would_block.

Sourceval try_with_access_shared_freezing : ('a : value_or_null) 'k. 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once portable unyielding -> 'a Await_kernel.Or_would_block.t @ unique once portable contended

try_with_access_shared_freezing t ~f is try_with_access_shared t ~f, but freezes t if f raises an uncaught exception.

Sourceval with_access_shared_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 Await_sync__.Rwlock.Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once) @ local once portable unyielding -> 'a Await_kernel.Or_canceled.t @ unique once portable contended

with_access_shared_or_cancel w c t ~f is Completed (with_access_shared w t ~f) if c is not canceled, otherwise it is Canceled.

Sourceval with_access_shared_or_cancel_freezing : ('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 Await_sync__.Rwlock.Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once) @ local once portable unyielding -> 'a Await_kernel.Or_canceled.t @ unique once portable contended

with_access_shared_or_cancel_freezing w c t ~f is with_access_shared_or_cancel w c t ~f, but freezes t if f raises an uncaught exception.

Uncontended for a writer

Sourceval with_access : ('a : value_or_null) 'k. Await_kernel.Sync.t @ local -> 'k t @ local -> f: (Await_kernel.Sync.t @ local -> ('k Await_sync__.Rwlock.Capsule.Access.t -> 'a @ unique once portable contended) @ local once) @ local once portable unyielding -> 'a @ unique once portable contended

with_access w t ~f acquires t for writing, runs f within the associated capsule, then releases t. If t is locked then uses w 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.

  • raises Frozen

    if t cannot be acquired for writing because it is frozen.

Sourceval with_access_poisoning : ('a : value_or_null) 'k. Await_kernel.Sync.t @ local -> 'k t @ local -> f: (Await_kernel.Sync.t @ local -> ('k Await_sync__.Rwlock.Capsule.Access.t -> 'a @ unique once portable contended) @ local once) @ local once portable unyielding -> 'a @ unique once portable contended

with_access_poisoning w t ~f is with_access w t ~f, but poisons t if f raises an uncaught exception.

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

try_with_access t ~f attempts to acquire t for writing without blocking. If successful, it runs f as with_access would, but without taking a Sync.t because no waiting is needed. Otherwise, it is Would_block.

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

try_with_access_poisoning t ~f is try_with_access t ~f, but poisons t if f raises an uncaught exception.

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 Await_sync__.Rwlock.Capsule.Access.t -> 'a @ unique once portable contended) @ local once) @ local once portable unyielding -> 'a Await_kernel.Or_canceled.t @ unique once portable contended

with_access_or_cancel w c t ~f is Completed (with_access w 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 Await_sync__.Rwlock.Capsule.Access.t -> 'a @ unique once portable contended) @ local once) @ local once portable unyielding -> 'a Await_kernel.Or_canceled.t @ unique once portable contended

with_access_or_cancel_poisoning w c t ~f is with_access_or_cancel w c t ~f, but poisons t if f raises an uncaught exception.

With a local Password

Password.Shared by readers

Sourceval with_password_shared : ('a : value_or_null) 'k. Await_kernel.Sync.t @ local -> 'k t @ local -> f: (Await_kernel.Sync.t @ local -> ('k Await_sync__.Rwlock.Capsule.Password.Shared.t @ local forkable -> 'a @ unique) @ local once) @ local once unyielding -> 'a @ unique

with_password_shared 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. 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 with_password_shared_freezing : ('a : value_or_null) 'k. Await_kernel.Sync.t @ local -> 'k t @ local -> f: (Await_kernel.Sync.t @ local -> ('k Await_sync__.Rwlock.Capsule.Password.Shared.t @ local forkable -> 'a @ unique) @ local once) @ local once unyielding -> 'a @ unique

with_password_shared_freezing w t ~f is with_password_shared w t ~f, but freezes t if f raises an uncaught exception.

Sourceval try_with_password_shared : ('a : value_or_null) 'k. 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Password.Shared.t @ local forkable -> 'a @ unique) @ local once unyielding -> 'a Await_kernel.Or_would_block.t @ unique

try_with_password_shared t ~f attempts to acquire t for reading without blocking. If successful, it runs f as with_password_shared would, but without taking a Sync.t because no waiting is needed. Otherwise, it is Would_block.

Sourceval try_with_password_shared_freezing : ('a : value_or_null) 'k. 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Password.Shared.t @ local forkable -> 'a @ unique) @ local once unyielding -> 'a Await_kernel.Or_would_block.t @ unique

try_with_password_shared_freezing t ~f is try_with_password_shared t ~f, but freezes t if f raises an uncaught exception.

Sourceval with_password_shared_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 Await_sync__.Rwlock.Capsule.Password.Shared.t @ local forkable -> 'a @ unique) @ local once) @ local once unyielding -> 'a Await_kernel.Or_canceled.t @ unique

with_password_shared_or_cancel w c t ~f is Completed (with_password_shared w t ~f) if c is not canceled, otherwise it is Canceled.

Sourceval with_password_shared_or_cancel_freezing : ('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 Await_sync__.Rwlock.Capsule.Password.Shared.t @ local forkable -> 'a @ unique) @ local once) @ local once unyielding -> 'a Await_kernel.Or_canceled.t @ unique

with_password_shared_or_cancel_freezing w c t ~f is with_password_shared_or_cancel w t ~f, but freezes t if f raises an uncaught exception.

Password for a writer

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

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

  • raises Frozen

    if t cannot be acquired for writing because it is frozen.

Sourceval with_password_poisoning : ('a : value_or_null) 'k. Await_kernel.Sync.t @ local -> 'k t @ local -> f: (Await_kernel.Sync.t @ local -> ('k Await_sync__.Rwlock.Capsule.Password.t @ local -> 'a @ unique) @ local once) @ local once unyielding -> 'a @ unique

with_password_poisoning w t ~f is with_password w t ~f, but poisons t if f raises an uncaught exception.

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

try_with_password t ~f attempts to acquire t for writing without blocking. If successful, it runs f as with_password would, but without taking a Sync.t because no waiting is needed. Otherwise, it is Would_block.

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

try_with_password_poisoning t ~f is try_with_password t ~f, but poisons t if f raises an uncaught exception.

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 Await_sync__.Rwlock.Capsule.Password.t @ local -> 'a @ unique) @ local once) @ local once unyielding -> 'a Await_kernel.Or_canceled.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.

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 Await_sync__.Rwlock.Capsule.Password.t @ local -> 'a @ unique) @ local once) @ local once unyielding -> 'a Await_kernel.Or_canceled.t @ unique

with_password_or_cancel_poisoning w c t ~f is with_password_or_cancel w c t ~f, but poisons t if f raises an uncaught exception.

With a 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 Await_sync__.Rwlock.Capsule.Key.t @ unique -> #('a * 'k Await_sync__.Rwlock.Capsule.Key.t) @ unique once) @ local once) @ local once unyielding -> 'a @ unique once

with_key_poisoning s t ~f locks t for writing and runs f, providing it a key for 'k uniquely. If t is locked for reading or writing, then with_key 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.

  • raises Frozen

    if t cannot be acquired for writing because it is frozen.

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

try_with_key_poisoning t ~f attempts to acquire t for writing without blocking. If successful, it runs f as with_key_poisoning would, but without taking a Sync.t because no waiting is needed. Otherwise, it is Would_block.

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 Await_sync__.Rwlock.Capsule.Key.t @ unique -> #('a * 'k Await_sync__.Rwlock.Capsule.Key.t) @ unique once) @ local once) @ local once unyielding -> 'a Await_kernel.Or_canceled.t @ unique once

with_key_or_cancel_poisoning w c t ~f is with_key_or_cancel w c t ~f, but poisons t if f raises an uncaught exception.

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 Await_sync__.Rwlock.Capsule.Key.t @ unique -> #('a * 'k Await_sync__.Rwlock.Capsule.Key.t) @ unique once) @ local once) @ local once) @ local once unyielding -> 'a @ unique once

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 Await_sync__.Rwlock.Capsule.Key.t @ unique -> #('a * 'k Await_sync__.Rwlock.Capsule.Key.t) @ unique once) @ local once) @ local once) @ local once unyielding -> 'a Await_kernel.Or_canceled.t @ unique once

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 poisoning indefinitely
Sourceval poison : 'k t @ local -> 'k Await_sync__.Rwlock.Capsule.Key.t @ unique -> 'k Await_sync__.Rwlock.Capsule.Key.t @ unique

poison t key poisons the rwlock associated with the key.

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

Poisoning as a signal

Sourceval is_poisoned : 'k t @ local -> bool

is_poisoned t is true if the reader-writer lock t is poisoned.

Sourceval is_frozen : 'k t @ local -> bool

is_frozen t is true if the reader-writer lock t is frozen.