Module Await_sync.Rwlock

A poisonable and freezable multiple readers, single writer lock.

module Capsule := Capsule.Expert

Creating a readers/writer lock

type 'k t

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

val create : ?padded:bool @ local -> ('k Capsule.Key.t @ unique -> 'k t) @ local @@ portable

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

val with_access_shared : 'a 'k. Await_kernel.Await.t @ local -> ('k t @ local -> (f: ('k Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once portable -> 'a @ unique once portable contended) @ local) @ local @@ portable

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.

val with_access_shared_freezing : 'a 'k. Await_kernel.Await.t @ local -> ('k t @ local -> (f: ('k Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once portable -> 'a @ unique once portable contended) @ local) @ local @@ portable

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

val with_access_shared_or_cancel : 'a 'k. Await_kernel.Await.t @ local -> (Await_kernel.Cancellation.t @ local -> ('k t @ local -> (f: ('k Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once portable -> 'a Await_kernel.Or_canceled.t @ unique once portable contended) @ local) @ local) @ local @@ portable

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.

val with_access_shared_or_cancel_freezing : 'a 'k. Await_kernel.Await.t @ local -> (Await_kernel.Cancellation.t @ local -> ('k t @ local -> (f: ('k Capsule.Access.t @ shared -> 'a @ unique once portable contended) @ local once portable -> 'a Await_kernel.Or_canceled.t @ unique once portable contended) @ local) @ local) @ local @@ portable

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

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

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.

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

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

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

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

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

val with_password_shared : 'a 'k. Await_kernel.Await.t @ local -> ('k t @ local -> (f:('k Capsule.Password.Shared.t @ local -> 'a @ unique) @ local once -> 'a @ unique) @ local) @ local @@ portable

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.

val with_password_shared_freezing : 'a 'k. Await_kernel.Await.t @ local -> ('k t @ local -> (f:('k Capsule.Password.Shared.t @ local -> 'a @ unique) @ local once -> 'a @ unique) @ local) @ local @@ portable

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

val with_password_shared_or_cancel : 'a 'k. Await_kernel.Await.t @ local -> (Await_kernel.Cancellation.t @ local -> ('k t @ local -> (f:('k Capsule.Password.Shared.t @ local -> 'a @ unique) @ local once -> 'a Await_kernel.Or_canceled.t @ unique) @ local) @ local) @ local @@ portable

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.

val with_password_shared_or_cancel_freezing : 'a 'k. Await_kernel.Await.t @ local -> (Await_kernel.Cancellation.t @ local -> ('k t @ local -> (f:('k Capsule.Password.Shared.t @ local -> 'a @ unique) @ local once -> 'a Await_kernel.Or_canceled.t @ unique) @ local) @ local) @ local @@ portable

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

val with_password : 'a 'k. Await_kernel.Await.t @ local -> ('k t @ local -> (f:('k Capsule.Password.t @ local -> 'a @ unique) @ local once -> 'a @ unique) @ local) @ local @@ 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 Frozen

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

  • raises Terminated

    if w is terminated before the lock is acquired.

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

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

val with_password_or_cancel : 'a 'k. Await_kernel.Await.t @ local -> (Await_kernel.Cancellation.t @ local -> ('k t @ local -> (f:('k Capsule.Password.t @ local -> 'a @ unique) @ local once -> 'a Await_kernel.Or_canceled.t @ unique) @ local) @ local) @ local @@ 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.

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

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

Aliased for readers
val with_key_shared : 'a 'k. Await_kernel.Await.t @ local -> ('k t @ local -> (f:('k Capsule.Key.t -> 'a @ unique once) @ local once -> 'a @ unique once) @ local) @ local

with_key_shared w t ~f locks t for reading and runs f, providing it an aliased key for 'k. If t is locked for writing, then with_key_shared uses w to wait 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.

val with_key_shared_freezing : 'a 'k. Await_kernel.Await.t @ local -> ('k t @ local -> (f:('k Capsule.Key.t -> 'a @ unique once) @ local once -> 'a @ unique once) @ local) @ local

with_key_shared_freezing w t ~f is with_key_shared w t ~f, but freezes t if f raises an uncaught exception.

val with_key_shared_or_cancel : 'a 'k. Await_kernel.Await.t @ local -> (Await_kernel.Cancellation.t @ local -> ('k t @ local -> (f:('k Capsule.Key.t -> 'a @ unique once) @ local once -> 'a Await_kernel.Or_canceled.t @ unique once) @ local) @ local) @ local

with_key_shared_or_cancel w c t ~f is Completed (with_key_shared w t ~f) if c is not canceled, otherwise it is Canceled

val with_key_shared_or_cancel_freezing : 'a 'k. Await_kernel.Await.t @ local -> (Await_kernel.Cancellation.t @ local -> ('k t @ local -> (f:('k Capsule.Key.t -> 'a @ unique once) @ local once -> 'a Await_kernel.Or_canceled.t @ unique once) @ local) @ local) @ local

with_key_shared_or_cancel_freezing w c t ~f is with_key_shared_or_cancel w c t ~f, but freezes t if f raises an uncaught exception.

Unique for a writer
val with_key : 'a 'k. Await_kernel.Await.t @ local -> ('k t @ local -> (f: ('k Capsule.Key.t @ unique -> #('a * 'k Capsule.Key.t) @ unique once) @ local once -> 'a @ unique once) @ local) @ local

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

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

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

val with_key_or_cancel : 'a 'k. Await_kernel.Await.t @ local -> (Await_kernel.Cancellation.t @ local -> ('k t @ local -> (f: ('k Capsule.Key.t @ unique -> #('a * 'k Capsule.Key.t) @ unique once) @ local once -> 'a Await_kernel.Or_canceled.t @ unique once) @ local) @ local) @ local

with_key_or_cancel w c t ~f is Completed (with_key w t ~f) if c is not canceled, otherwise it is Canceled

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

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.

Aliased for readers
Unique for a writer
And waiting for a Condition
module Condition : sig ... end

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

And poisoning indefinitely
val poison : 'k t @ local -> ('k Capsule.Key.t @ unique -> 'k Capsule.Key.t @ unique) @ local @@ portable

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

module Shared_guard : sig ... end
val acquire_shared : Await_kernel.Await.t @ local -> ('k t -> 'k Shared_guard.t @ unique) @ local @@ portable

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.

val 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) @ local) @ local @@ portable

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

module Guard : sig ... end
val acquire : Await_kernel.Await.t @ local -> ('k t -> 'k Guard.t @ unique) @ local @@ portable

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.

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

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

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

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

val is_frozen : 'k t @ local -> bool @@ portable

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