Legend:
Library
Module
Module type
Parameter
Class
Class type
A value that will become determined asynchronously.
A deferred can be "undetermined" or "determined". A deferred that is undetermined may at some point become determined with value v, and will henceforth always be determined with value v.
type+'a t = 'aAsync_kernel__.Types.Deferred.t
val sexp_of_t : ('a->Sexplib0.Sexp.t)->'at->Sexplib0.Sexp.t
includeCore.Invariant.S1 withtype'a t := 'at
val invariant : 'aBase__Invariant_intf.inv->'atBase__Invariant_intf.inv
sexp_of_t t f returns a sexp of the deferred's value, if it is determined, or an informative string otherwise.
This is just for display purposes. There is no t_of_sexp.
let%bind v = t in f v returns a deferred t' that waits until t is determined with value v, at which point it waits for f v to become determined with value v', to which t' will become determined.
return v returns a deferred that is immediately determined with value v.
Note that:
upon t f
is more efficient than:
ignore (let%bind a = t in f a; return ())
because upon, unlike let%bind, does not create a deferred to hold the result.
For example, one can write a loop that has good constant factors with:
let rec loop () =
upon t (fun a -> ... loop () ... )
although often forever or repeat_until_finished is more clear.
The same loop written with let%bind would allocate deferreds that would be immediately garbage collected. (In the past, this loop would have also used linear space in recursion depth!)
In general, for deferreds that are allocated by let%bind to be garbage collected quickly, it is sufficient that the allocating bind be executed in tail-call position of the right-hand side of an outer bind.
choice t g corresponds to one alternative to use in choose.
One needs to be mindful of memory leaks and effect leaks when using this interface: if the corresponding choice is not taken, then t is simply discarded (as if don't_wait_for was called), but any work that was scheduled to make t determined won't be cancelled automatically.
This means that something as simple as choice (map d ~f) g creates a leak: it adds a handler f to d, which will still run if d is filled (effect leak), or stay in memory until the subroutine responsible for filling this ivar drops it (memory leak).
To avoid this memory leak it's sufficient to choose on an pre-existing ivar, whose lifetime is controlled separately. For example:
use Pipe.read_choice, not Pipe.read,
use Clock.Event.fired, not Clock.after (then cancel the event).
enabled [choice t1 f1; ... choice tn fn;] returns a deferred d that becomes determined when any of the ti becomes determined. The value of d is a function f that when called, for each ti that is enabled, applies fi to ti, and returns a list of the results. It is guaranteed that the list is in the same order as the choices supplied to enabled, but of course it may be shorter than the input list if not all ti are determined.
returns a deferred t that becomes determined with value fi ai after some ti becomes determined with value ai. It is guaranteed that choose calls at most one of the fis, the one that determines its result. There is no guarantee that the ti that becomes determined earliest in time will be the one whose value determines the choose. Nor is it guaranteed that the value in t is the first value (in place order) from choices that is determined at the time t is examined.
it may be the case that both t1 and t2 become determined, yet e2 actually runs.
It is guaranteed that if multiple choices are determined with no intervening asynchrony, then the earliest choice in the list will become the value of the choose.
val for_ : int ->to_:int ->do_:(int ->unit t)->unit t
for_ start ~to_:stop ~do_:f is the deferred analog of:
for i = start to stop do
f i;
done
val repeat_until_finished :
'state->('state->[ `Repeat of 'state| `Finished of 'result ]t)->'resultt
repeat_until_finished initial_state f repeatedly runs f until f returns `Finished. The first call to f happens immediately when repeat_until_finished is called.
All Deferred_queue iteration functions first copy the queue (to a list) and then start calling the user function f. So, if f modifies the queue, that will have no effect on the iteration.
These contain interfaces for working with deferred type containing error-aware types, like 'a Option.t Deferred.t, or 'a Or_error.t Deferred.t. These all include support for monadic programming.