package async_kernel
Install
Dune Dependency
Authors
Maintainers
Sources
sha256=01ced973dbc70535f692f38bed524ae82dba17e26e58791b2fbf0d647b160d2e
doc/async_kernel/Async_kernel/Mvar/index.html
Module Async_kernel.Mvar
Source
An Mvar
is a mutable location that is either empty or contains a value. One can put
or set
the value, and wait on value_available
for the location to be filled in either way.
Having an Mvar.Read_write.t
gives the capability to mutate the mvar.
The key difference between an Mvar
and an Ivar
is that an Mvar
may be filled multiple times.
This implementation of Mvar
also allows one to replace the value without any guarantee that the reading side has seen it. This is useful in situations where last-value semantics are desired (e.g., you want to signal whenever a config file is updated, but only care about the most recent contents).
An Mvar
can also be used as a baton-passing mechanism between a producer and consumer. For instance, a producer reading from a socket and producing a set of deserialized messages can put
the batch from a single read into an Mvar
and can wait for taken
to return as a pushback mechanism. The consumer meanwhile waits on value_available
. This way the natural batch size is passed between the two sub-systems with minimal overhead.
val sexp_of_t :
('a -> Sexplib0.Sexp.t) ->
('phantom -> Sexplib0.Sexp.t) ->
('a, 'phantom) t ->
Sexplib0.Sexp.t
put t a
waits until is_empty t
, and then does set t a
. If there are multiple concurrent put
s, there is no fairness guarantee (i.e., put
s may happen out of order or may be starved).
set t a
sets the value in t
to a
, even if not (is_empty t)
. This is useful if you want takers to have last-value semantics.
update t ~f
applies f
to the value in t
and set
s t
to the result. This is useful if you want takers to have accumulated-value semantics.
update_exn
is like update
, except it raises if is_empty t
.
value_available t
returns a deferred d
that becomes determined when a value is in t
. d
does not include the value in t
because that value may change after d
becomes determined and before a deferred bind on d
gets to run.
Repeated calls to value_available t
will always return the same deferred until the t
is filled.
take t
returns a deferred that, when t
is filled, becomes determined with the value of t
and clears t
. If there are multiple concurrent calls to take
then only one of them will be fulfilled and the others will continue waiting on future values. There is no ordering guarantee for which take
call will be filled first.
taken t
returns a deferred that is filled the next time take
clears t
.
peek t
returns the value in t
without clearing t
, or returns None
is is_empty t
.
peek_exn t
is like peek
, except it raises if is_empty t
.
pipe_when_ready t
returns a pipe, then repeatedly takes a value from t
and writes it to the pipe. After each write, pipe_when_ready
waits for the pipe to be ready to accept another value before taking the next value. Once the pipe is closed, pipe_when_ready
will no longer take values from t
.
Notice that this implementation effectively creates an extra buffer of size 1, so when you read from the pipe you can read a stale value (even though a fresh one should come immediately afterwards), and a value will be taken from the MVar even if it's never read from the pipe.
There is no protection against creating multiple pipes or otherwise multiple things trying to take
concurrently. If that happens, it's not specified which of the pipes will get the value.