Module Tenacious_lib.Tenacious

include Tenacious_intf.S
val version : string
val init : concurrency:int ‑> unit

To be called to set the amount of concurrency allowed before any call to exec.

include Core.Monad.S
type 'a t
include Base__.Monad_intf.S_without_syntax with type t := a t
type 'a t

A monad is an abstraction of the concept of sequencing of computations. A value of type 'a monad represents a computation that returns a value of type 'a.

include Base__.Monad_intf.Infix with type t := a t
type 'a t
val (>>=) : 'a t ‑> ('a ‑> 'b t) ‑> 'b t

t >>= f returns a computation that sequences the computations represented by two monad elements. The resulting computation first does t to yield a value v, and then runs the computation returned by f v.

val (>>|) : 'a t ‑> ('a ‑> 'b) ‑> 'b t

t >>| f is t >>= (fun a -> return (f a)).

module Monad_infix : Base__.Monad_intf.Infix with type t := a t
val bind : 'a t ‑> f:('a ‑> 'b t) ‑> 'b t

bind t ~f = t >>= f

val return : 'a ‑> 'a t

return v returns the (trivial) computation that returns v.

val map : 'a t ‑> f:('a ‑> 'b) ‑> 'b t

map t ~f is t >>| f.

val join : 'a t t ‑> 'a t

join t is t >>= (fun t' -> t').

val ignore_m : 'a t ‑> unit t

ignore_m t is map t ~f:(fun _ -> ()). ignore_m used to be called ignore, but we decided that was a bad name, because it shadowed the widely used Pervasives.ignore. Some monads still do let ignore = ignore_m for historical reasons.

val all : 'a t list ‑> 'a list t
val all_ignore : unit t list ‑> unit t
include Base__.Monad_intf.Syntax with type t := a t
type 'a t
module Let_syntax : sig ... end
type 'a tenacious = 'a t
val all_unit : unit t list ‑> unit t
val map2 : 'a t ‑> 'b t ‑> f:('a ‑> 'b ‑> 'c) ‑> 'c t
val both : 'a t ‑> 'b t ‑> ('a * 'b) t
val exec : 'a t ‑> name:Core.String.t Core.Lazy.t ‑> ('a * Heart.t) Async.Deferred.t

note that exec adds a new root in the observable tenacious graph, even if you call it from a function given to embed or lift.

val embed : (cancel:Heart.t ‑> ('a * Heart.t) option Async.Deferred.t) ‑> 'a t
val memoize : name:Core.String.t Core.Lazy.t ‑> 'a t ‑> 'a t
val bracket : 'a t ‑> running:(int ‑> unit) ‑> finished:('a ‑> unit) ‑> cancelled:(unit ‑> unit) ‑> 'a t

This is most useful in combination with memoize: memoize (bracket ~running ~finished ~cancelled x). Without memoize, you can get multiple concurrent running..canceled and running..finished blocks even when your tenacious doesn't breaks its heart.

val uncancellable : 'a t ‑> 'a t
val desensitize : 'a t ‑> ('a * Heart.t) t
val lift : (unit ‑> ('a * Heart.t) Async.Deferred.t) ‑> 'a t

lift is specialization/simplification of embed

val cutoff : equal:('a ‑> 'a ‑> bool) ‑> 'a t ‑> 'a t

cutoff is dangerous: it will delay heart breakage for the time it takes to re-compute the value so evaluating a memoize (cutoff x) might give you stale values even when memoize x wouldn't.

We have had a solution in the form of val protecting_cutoffs : 'a t -> 'a t that would only return a value after waiting for all cutoffs to finish. We removed the function right after f322aafe57c1 because it was unused and was preventing an optimization for Heart.or_broken.

val race : 'a t ‑> 'a t ‑> 'a t

race non-deterministically chooses the first computation to succeed, cancels the other.

Note that as it's non-deterministic it should be used with care. Ideally the final result should not depend on which result gets produced first.

module Stream : sig ... end

Stream provides two things:

module Result : sig ... end
val race_error : ('a'eResult.t ‑> ('b'eResult.t ‑> f:('a ‑> 'b ‑> 'c) ‑> ('c'eResult.t

non-deterministically choose the faster one to fail. if neither fails, returns both. The race caveats apply.

val race_errors : ('a'eResult.t list ‑> ('a list, 'eResult.t
module Var : sig ... end with type ten := a t

A mutable variable whose state can be watched as a Tenacious computation. 'a Var.t is conceptually a 'a Ref.t with Var.{create,get,set,replace} corresponding to Ref.{create,(!),(:=),replace}. The important difference is the watch function, that lets you construct tenacious computations that depend on the value of the variable.

module For_tests : Tenacious_intf.For_tests with type t := a t