Module Await.RwlockSource

A poisonable and freezable multiple readers, single writer lock that can be acquired for an unbounded 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.Await.t @ local -> 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once portable -> '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.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Terminated

    if w is terminated before the lock is acquired.

Sourceval with_access_shared_freezing : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once portable -> '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 -> '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 Await.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 -> '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.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once portable -> '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.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once portable -> '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.Await.t @ local -> 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Access.t -> 'a @ unique once portable contended) @ local once portable -> '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.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Frozen

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

  • raises Terminated

    if w is terminated before the lock is acquired.

Sourceval with_access_poisoning : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Access.t -> 'a @ unique once portable contended) @ local once portable -> '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 -> '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 an Await.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 -> '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.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Access.t -> 'a @ unique once portable contended) @ local once portable -> '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.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Access.t -> 'a @ unique once portable contended) @ local once portable -> '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.Shared by readers

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

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Terminated

    if w is terminated before the lock is acquired.

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

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Frozen

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

  • raises Terminated

    if w is terminated before the lock is acquired.

Sourceval with_password_poisoning : ('a : value_or_null) 'k. Await_kernel.Await.t @ local -> 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Password.t @ local -> 'a @ unique) @ local once -> '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 -> '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 an Await.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 -> '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.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Password.t @ local -> 'a @ unique) @ local once -> '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.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Password.t @ local -> 'a @ unique) @ local once -> '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.Await.t @ local -> 'k t @ local -> f: ('k Await_sync__.Rwlock.Capsule.Key.t @ unique -> #('a * 'k Await_sync__.Rwlock.Capsule.Key.t) @ unique once) @ local once -> 'a @ unique once

with_key_poisoning w t ~f is with_key w t ~f, but poisons t if f raises an uncaught exception.

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 -> '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 Await.t because no waiting is needed. Otherwise, it is Would_block.

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

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

With arbitrary dynamic scope

For readers

Sourcemodule Shared_guard : sig ... end
Sourceval acquire_shared : Await_kernel.Await.t @ local -> 'k t -> 'k Shared_guard.t @ unique

acquire_shared w t acquires t for reading and returns a Shared_guard.t for the lock. If t is already locked for writing, acquire_shared uses w to block until it is only locked for reading.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Terminated

    if w is terminated before the lock is acquired.

Sourceval try_acquire_shared : 'k t -> 'k Shared_guard.t Await_kernel.Or_would_block.t @ unique

try_acquire_shared t attempts to acquire t for reading without blocking, and does not take an Await.t because no waiting is needed. It is Would_block if t is locked for writing.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

Sourceval acquire_shared_or_cancel : Await_kernel.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t -> 'k Shared_guard.t Await_kernel.Or_canceled.t @ unique

acquire_shared_or_cancel w c t is Completed (acquire_shared w t) if c is not canceled, otherwise it is Canceled.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Terminated

    if w is terminated before the lock is acquired, even if c is canceled.

For a writer

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

acquire w t acquires t for writing and returns a Write_guard.t for the lock. If t is already locked for reading or writing, acquire uses w to block until it is unlocked.

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Frozen

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

  • raises Terminated

    if w is terminated before the lock is acquired.

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

try_acquire t attempts to acquire t for writing without blocking, and does not take an Await.t because no waiting is needed. It is Would_block if t is locked.

  • 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 acquire_or_cancel : Await_kernel.Await.t @ local -> Await_kernel.Cancellation.t @ local -> 'k t -> 'k Guard.t Await_kernel.Or_canceled.t @ unique

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

  • raises Poisoned

    if t cannot be acquired because it is poisoned.

  • raises Frozen

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

  • raises Terminated

    if w is terminated before the lock is acquired, even if c is canceled.

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.