Module Await_sync.Awaitable

An awaitable represents an atomic location whose change of value can be awaited upon. Awaitables can be used to implement all kinds of blocking data structures, including locks, condition variables, and blocking queues.

Atomic API

type !('a : value_or_null) t

An awaitable atomic reference to a value of type 'a.

val make : 'a. ?padded:bool @ local -> ('a @ portable contended -> 'a t) @ local @@ portable

make v creates a new awaitable atomic reference with the given initial value v.

The optional padded argument specifies whether to pad the data structure to avoid false sharing. See Atomic.make for a longer explanation.

val get : 'a. 'a t @ local -> 'a @ portable contended @@ portable

get t gets the current value of the awaitable atomic reference.

val set : 'a. 'a t @ local -> ('a @ portable contended -> unit) @ local @@ portable

set t v sets a new value v for the awaitable atomic reference.

val exchange : 'a. 'a t @ local -> ('a @ portable contended -> 'a @ portable contended) @ local @@ portable

exchange t v sets a new value v for the awaitable atomic reference and returns the current value.

module Compare_failed_or_set_here = Portable_kernel.Atomic.Compare_failed_or_set_here
val compare_and_set : 'a. 'a t @ local -> (if_phys_equal_to:'a @ portable contended -> (replace_with:'a @ portable contended -> Compare_failed_or_set_here.t) @ local) @ local @@ portable

compare_and_set t ~if_phys_equal_to:seen ~replace_with:v sets the new value of t to v only if its current value is physically equal to seen -- the comparison and the set occur atomically. Returns true if the comparison succeeded (so the set happened) and false otherwise.

val compare_exchange : 'a. 'a t @ local -> (if_phys_equal_to:'a @ portable contended -> (replace_with:'a @ portable contended -> 'a @ portable contended) @ local) @ local @@ portable

compare_exchange t ~if_phys_equal_to:seen ~replace_with:v sets the new value of s to v only if its current value is physically equal to seen -- the comparison and the set occur atomically. Returns the previous value.

val fetch_and_add : int t @ local -> (int -> int) @ local @@ portable

fetch_and_add t n atomically increments the value of t by n, and returns the current value (before the increment).

val incr : int t @ local -> unit @@ portable

incr t atomically increments the value of t by 1.

val decr : int t @ local -> unit @@ portable

decr t atomically decrements the value of t by 1.

val update : 'a. 'a t @ local -> (pure_f:('a @ portable contended -> 'a @ portable contended) @ local -> unit) @ local @@ portable

update t ~pure_f atomically updates t to be the result of pure_f (get t). pure_f may be called multiple times, so should be free of side effects.

val get_and_update : 'a. 'a t @ local -> (pure_f:('a @ portable contended -> 'a @ portable contended) @ local -> 'a @ portable contended) @ local @@ portable

get_and_update t ~pure_f atomically updates t to be the result of pure_f (get t). pure_f may be called multiple times, so should be free of side effects. Returns the old value.

Futex API

type _ await =
  1. | Signaled : [> `Signaled ] await
  2. | Terminated : [> `Terminated ] await
  3. | Canceled : [> `Canceled ] await

Result of await or await_or_cancel.

val await : 'a. Await_kernel.Await.t @ local -> ('a t @ local -> (until_phys_unequal_to:'a @ portable contended -> [ `Signaled | `Terminated ] await) @ local) @ local @@ portable

await w t ~until_phys_unequal_to:v suspends the caller until the awaitable t is explicitly signaled and/or has a value physically unequal to v.

The return value is Signaled in case the await was woken up due to a signal or broadcast on the awaitable. Otherwise the return value is Terminated.

This operation is subject to the ABA problem. An await for a value other than A may not return after the awaitable is signaled while having the value B, because at a later point the awaitable has again the value A. Furthermore, by the time an await for value other than A returns, the awaitable might already again have the value A.

Atomic operations that change the value of an awaitable do not implicitly wake up awaiters.

await establishes a happens-before relationship with any reads and writes on the current thread that precede it, and the comparison of the current value of the awaitable t with the given value v.

val await_or_cancel : 'a. Await_kernel.Await.t @ local -> (Await_kernel.Cancellation.t @ local -> ('a t @ local -> (until_phys_unequal_to:'a @ portable contended -> [ `Signaled | `Terminated | `Canceled ] await) @ local) @ local) @ local @@ portable

await_or_cancel w c t ~until_phys_unequal_to:v is like await w t ~until_phys_unequal_to:v, but the caller will also be resumed in case the cancellation token c becomes canceled.

The return value is Signaled in case the await was woken up due to a signal or broadcast on the awaitable. Otherwise the return value is either Terminated in case w is terminated, and Canceled in case c is canceled.

val signal : 'a. 'a t @ local -> unit @@ portable

signal t tries to wake up at least one awaiter on the awaitable location t.

val broadcast : 'a. 'a t @ local -> unit @@ portable

broadcast t tries to wake up all the awaiters on the awaitable location t.

module Awaiter : sig ... end

An expert interface that allows an await to be setup separately from suspending the thread of control. This makes it possible to e.g. implement condition variables, which requires setting up the await before unlocking the associated mutex, and also makes it possible to await for one of many things.

module For_testing : sig ... end