Await_sync.AtomAn atom is intended to be an easy-to-use waitable atomic location for storing state represented as an immutable data structure.
The key feature of atom over Atomic and Awaitable is that update operations use an approach to make starvation unlikely. No matter how expensive the function given to update is, the update should be unlikely to starve. The starvation avoiding approach adds a bit of overhead over Atomic and Awaitable, but should make Atom easier to use.
val make :
?padded:bool @ local ->
('a @ portable contended ->
'a t) @ local @@ portablemake value creates an atom with the given initial value.
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 t @ local -> 'a @ portable contended @@ portableget t gets the the current value of t.
This is a wait-free operation and returns a value even after the atom has become poisoned.
val poison : _ t -> unit @@ portablepoison t poisons the atom.
If a pure_f given to update raises an exception, it will be reraised by at most one of the threads trying to concurrently poison, update, or wait on the atom, and the atom will be poisoned.
In other words, poison only raises in case a concurrent update raised. The idea is that the atom implementation makes sure that at least one exception raised by a pure_f given to a concurrent update will be reraised.
val update :
'a t @ local ->
(pure_f:('a @ portable contended -> 'a @ portable contended) @ portable ->
unit) @ local @@ portableupdate 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.
While this is technically not a wait-free operation, starvation should be unlikely.
If a pure_f given to update raises an exception, it will be reraised by at most one of the threads trying to concurrently poison, update, or wait on the atom, and the atom will be poisoned.
val get_and_update :
'a t @ local ->
(pure_f:('a @ portable contended -> 'a @ portable contended) @ portable ->
'a @ portable contended) @ local @@ portableget_and_update t ~pure_f is like update t ~pure_f, but also returns the old value of the atom.
val wait :
Await_kernel.Await.t @ local ->
('a t @ local ->
(until_phys_unequal_to:'a @ portable contended ->
unit) @ local) @ local @@ portablewait w t ~until_phys_unequal_to waits until the current value of t is physically unequal to given value.
It is not guaranteed that wait returns after every update. In other words, wait may miss updates and only returns after a physically unequal value is witnessed.
If a pure_f given to update raises an exception, it will be reraised by at most one of the threads trying to concurrently poison, update, or wait on the atom, and the atom will be poisoned.
val wait_and_return :
Await_kernel.Await.t @ local ->
('a t @ local ->
(until_phys_unequal_to:'a @ portable contended ->
'a @ portable contended) @ local) @ local @@ portablewait_and_return w t ~until_phys_unequal_to is like wait w t ~until_phys_unequal_to, but also returns the current value.
val wait_for :
Await_kernel.Await.t @ local ->
('a t @ local ->
(f:('a @ portable contended -> bool) @ local ->
unit) @ local) @ local @@ portableval wait_for_and_return :
Await_kernel.Await.t @ local ->
('a t @ local ->
(f:('a @ portable contended -> bool) @ local ->
'a @ portable contended) @ local) @ local @@ portablewait_for_and_return w t ~f is like wait_for w t ~f, but also returns the current value.