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.Writer.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.
include sig ... endval sexp_of_t : ('a ‑> Base.Sexp.t) ‑> ('phantom ‑> Base.Sexp.t) ‑> ('a, 'phantom) t ‑> Base.Sexp.tmodule Read_write : sig ... endmodule Read_only : sig ... endval create : unit ‑> 'a Read_write.tval is_empty : (_, _) t ‑> boolval put : ('a, [> Core_kernel.write ]) t ‑> 'a ‑> unit Deferred.tput t a waits until is_empty t, and then does set t a. If there are multiple
concurrent puts, there is no fairness guarantee (i.e., puts may happen out of
order or may be starved).
val set : ('a, [> Core_kernel.write ]) t ‑> 'a ‑> unitset 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.
val update : ('a, Core_kernel.read_write) t ‑> f:('a option ‑> 'a) ‑> unitupdate t ~f applies f to the value in t and sets t to the result. This is
useful if you want takers to have accumulated-value semantics.
val update_exn : ('a, Core_kernel.read_write) t ‑> f:('a ‑> 'a) ‑> unitupdate_exn is like update, except it raises if is_empty t.
val read_only : ('a, [> Core_kernel.read ]) t ‑> ('a, Core_kernel.read) tval write_only : ('a, [> Core_kernel.write ]) t ‑> ('a, Core_kernel.write) tval value_available : (_, [> Core_kernel.read ]) t ‑> unit Deferred.tvalue_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.
val take : ('a, [> Core_kernel.read ]) t ‑> 'a Deferred.ttake t returns a deferred that, when t is filled, becomes determined with the
value of t and 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.
val take_now_exn : ('a, [> Core_kernel.read ]) t ‑> 'aval taken : (_, [> Core_kernel.write ]) t ‑> unit Deferred.ttaken t returns a deferred that is filled the next time take clears t.
val peek : ('a, [> Core_kernel.read ]) t ‑> 'a optionpeek t returns the value in t without clearing t, or returns None is is_empty
t.
val peek_exn : ('a, [> Core_kernel.read ]) t ‑> 'apeek_exn t is like peek, except it raises if is_empty t.
val pipe_when_ready : ('a, [> Core_kernel.read ]) t ‑> 'a Pipe.Reader.tpipe_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.