diff --git a/moonpool-lwt/_doc-dir/README.md b/moonpool-lwt/_doc-dir/README.md index 2c7e88de..810bea41 100644 --- a/moonpool-lwt/_doc-dir/README.md +++ b/moonpool-lwt/_doc-dir/README.md @@ -173,49 +173,9 @@ val expected_sum : int = 5050 We have a `Exn_bt.t` type that comes in handy in many places. It bundles together an exception and the backtrace associated with the place the exception was caught. -### Fibers +### Local storage -On OCaml 5, Moonpool comes with a library `moonpool.fib` (module `Moonpool_fib`) -which provides _lightweight fibers_ -that can run on any Moonpool runner. -These fibers are a sort of lightweight thread, dispatched on the runner's -background thread(s). -Fibers rely on effects to implement `Fiber.await`, suspending themselves until the `await`-ed fiber -is done. - -```ocaml -# #require "moonpool.fib";; -... - -# (* convenient alias *) - module F = Moonpool_fib;; -module F = Moonpool_fib -# F.main (fun _runner -> - let f1 = F.spawn (fun () -> fib 10) in - let f2 = F.spawn (fun () -> fib 15) in - F.await f1 + F.await f2);; -- : int = 1076 -``` - -Fibers form a _tree_, where a fiber calling `Fiber.spawn` to start a sub-fiber is -the sub-fiber's _parent_. -When a parent fails, all its children are cancelled (forced to fail). -This is a simple form of [Structured Concurrency](https://en.wikipedia.org/wiki/Structured_concurrency). - -Like a future, a fiber eventually _resolves_ into a value (or an `Exn_bt.t`) that it's possible -to `await`. With `Fiber.res : 'a Fiber.t -> 'a Fut.t` it's possible to access that result -as a regular future, too. -However, this resolution is only done after all the children of the fiber have -resolved — the lifetime of fibers forms a well-nested tree in that sense. - -When a fiber is suspended because it `await`s another fiber (or future), the scheduler's -thread on which it was running becomes available again and can go on process another task. -When the fiber resumes, it will automatically be re-scheduled on the same runner it started on. -This means fibers on pool P1 can await fibers from pool P2 and still be resumed on P1. - -In addition to all that, fibers provide _fiber local storage_ (like thread-local storage, but per fiber). -This storage is inherited in `spawn` (as a shallow copy only — it's advisable to only -put persistent data in storage to avoid confusing aliasing). +Moonpool, via picos, provides _task local storage_ (like thread-local storage, but per task). The storage is convenient for carrying around context for cross-cutting concerns such as logging or tracing (e.g. a log tag for the current user or request ID, or a tracing scope). diff --git a/moonpool/Moonpool/Background_thread/index.html b/moonpool/Moonpool/Background_thread/index.html index 9d084841..61ff567a 100644 --- a/moonpool/Moonpool/Background_thread/index.html +++ b/moonpool/Moonpool/Background_thread/index.html @@ -3,6 +3,5 @@ ?on_init_thread:(dom_id:int -> t_id:int -> unit -> unit) -> ?on_exit_thread:(dom_id:int -> t_id:int -> unit -> unit) -> ?on_exn:(exn -> Stdlib.Printexc.raw_backtrace -> unit) -> - ?around_task:((t -> 'b) * (t -> 'b -> unit)) -> ?name:string -> 'a

Arguments used in create. See create for explanations.

val create : (unit -> t, _) create_args

Create the background runner

val with_ : (unit -> (t -> 'a) -> 'a, _) create_args
diff --git a/moonpool/Moonpool/Fifo_pool/index.html b/moonpool/Moonpool/Fifo_pool/index.html index 41c05c2b..91417144 100644 --- a/moonpool/Moonpool/Fifo_pool/index.html +++ b/moonpool/Moonpool/Fifo_pool/index.html @@ -3,7 +3,6 @@ ?on_init_thread:(dom_id:int -> t_id:int -> unit -> unit) -> ?on_exit_thread:(dom_id:int -> t_id:int -> unit -> unit) -> ?on_exn:(exn -> Stdlib.Printexc.raw_backtrace -> unit) -> - ?around_task:((t -> 'b) * (t -> 'b -> unit)) -> ?num_threads:int -> ?name:string -> - 'a

Arguments used in create. See create for explanations.

val create : (unit -> t, _) create_args

create () makes a new thread pool.

val with_ : (unit -> (t -> 'a) -> 'a, _) create_args

with_ () f calls f pool, where pool is obtained via create. When f pool returns or fails, pool is shutdown and its resources are released. Most parameters are the same as in create.

+ 'a

Arguments used in create. See create for explanations.

val create : (unit -> t, _) create_args

create () makes a new thread pool.

val with_ : (unit -> (t -> 'a) -> 'a, _) create_args

with_ () f calls f pool, where pool is obtained via create. When f pool returns or fails, pool is shutdown and its resources are released. Most parameters are the same as in create.

diff --git a/moonpool/Moonpool/Fut/Advanced/index.html b/moonpool/Moonpool/Fut/Advanced/index.html index 942041d5..5b4fd0a1 100644 --- a/moonpool/Moonpool/Fut/Advanced/index.html +++ b/moonpool/Moonpool/Fut/Advanced/index.html @@ -1,5 +1,5 @@ -Advanced (moonpool.Moonpool.Fut.Advanced)

Module Fut.Advanced

val barrier_on_abstract_container_of_futures : +Advanced (moonpool.Moonpool.Fut.Advanced)

Module Fut.Advanced

Advanced primitives for synchronization

val barrier_on_abstract_container_of_futures : iter:(('a t -> unit) -> 'cont -> unit) -> len:('cont -> int) -> aggregate_results:(('a t -> 'a) -> 'cont -> 'res) -> diff --git a/moonpool/Moonpool/Fut/index.html b/moonpool/Moonpool/Fut/index.html index 022c70c0..712ca388 100644 --- a/moonpool/Moonpool/Fut/index.html +++ b/moonpool/Moonpool/Fut/index.html @@ -1,3 +1,3 @@ -Fut (moonpool.Moonpool.Fut)

Module Moonpool.Fut

Futures.

A future of type 'a t represents the result of a computation that will yield a value of type 'a.

Typically, the computation is running on a thread pool Runner.t and will proceed on some worker. Once set, a future cannot change. It either succeeds (storing a Ok x with x: 'a), or fail (storing a Error (exn, bt) with an exception and the corresponding backtrace).

Combinators such as map and join_array can be used to produce futures from other futures (in a monadic way). Some combinators take a on argument to specify a runner on which the intermediate computation takes place; for example map ~on:pool ~f fut maps the value in fut using function f, applicatively; the call to f happens on the runner pool (once fut resolves successfully with a value).

type 'a or_error = ('a, Exn_bt.t) result
type 'a t = 'a Picos.Computation.t

A future with a result of type 'a.

type 'a promise = private 'a t

A promise, which can be fulfilled exactly once to set the corresponding future. This is a private alias of 'a t since 0.7, previously it was opaque.

val make : unit -> 'a t * 'a promise

Make a new future with the associated promise.

val make_promise : unit -> 'a promise

Same as make but returns a single promise (which can be upcast to a future). This is useful mostly to preserve memory.

How to upcast to a future in the worst case:

  let prom = Fut.make_promise ()
-  let fut = (prom : _ Fut.promise :> _ Fut.t)
  • since 0.7
val on_result : 'a t -> ('a or_error -> unit) -> unit

on_result fut f registers f to be called in the future when fut is set ; or calls f immediately if fut is already set.

val on_result_ignore : _ t -> (Exn_bt.t option -> unit) -> unit

on_result_ignore fut f registers f to be called in the future when fut is set; or calls f immediately if fut is already set. It does not pass the result, only a success/error signal.

  • since 0.7
exception Already_fulfilled
val try_cancel : _ promise -> Exn_bt.t -> bool

try_cancel promise ebt tries to cancel the promise, returning true. It returns false if the promise is already resolved.

  • since NEXT_RELEASE
val cancel : _ promise -> Exn_bt.t -> unit

Silent version of try_cancel, ignoring the result.

  • since NEXT_RELEASE
val fulfill : 'a promise -> 'a or_error -> unit

Fullfill the promise, setting the future at the same time.

val fulfill_idempotent : 'a promise -> 'a or_error -> unit

Fullfill the promise, setting the future at the same time. Does nothing if the promise is already fulfilled.

val return : 'a -> 'a t

Already settled future, with a result

val fail : exn -> Stdlib.Printexc.raw_backtrace -> _ t

Already settled future, with a failure

val fail_exn_bt : Exn_bt.t -> _ t

Fail from a bundle of exception and backtrace

  • since 0.6
val of_result : 'a or_error -> 'a t
val is_resolved : _ t -> bool

is_resolved fut is true iff fut is resolved.

val peek : 'a t -> 'a or_error option

peek fut returns Some r if fut is currently resolved with r, and None if fut is not resolved yet.

exception Not_ready
  • since 0.2
val get_or_fail : 'a t -> 'a or_error

get_or_fail fut obtains the result from fut if it's fulfilled (i.e. if peek fut returns Some res, get_or_fail fut returns res).

  • since 0.2
val get_or_fail_exn : 'a t -> 'a

get_or_fail_exn fut obtains the result from fut if it's fulfilled, like get_or_fail. If the result is an Error _, the exception inside is re-raised.

  • since 0.2
val is_done : _ t -> bool

Is the future resolved? This is the same as peek fut |> Option.is_some.

  • since 0.2
val is_success : _ t -> bool

Checks if the future is resolved with Ok _ as a result.

  • since 0.6
val is_failed : _ t -> bool

Checks if the future is resolved with Error _ as a result.

  • since 0.6
val raise_if_failed : _ t -> unit

raise_if_failed fut raises e if fut failed with e.

  • since 0.6

Combinators

val spawn : on:Runner.t -> (unit -> 'a) -> 'a t

spaw ~on f runs f() on the given runner on, and return a future that will hold its result.

val spawn_on_current_runner : (unit -> 'a) -> 'a t

This must be run from inside a runner, and schedules the new task on it as well.

See Runner.get_current_runner to see how the runner is found.

  • since 0.5
  • raises Failure

    if run from outside a runner.

val reify_error : 'a t -> 'a or_error t

reify_error fut turns a failing future into a non-failing one that contain Error (exn, bt). A non-failing future returning x is turned into Ok x

  • since 0.4
val map : ?on:Runner.t -> f:('a -> 'b) -> 'a t -> 'b t

map ?on ~f fut returns a new future fut2 that resolves with f x if fut resolved with x; and fails with e if fut fails with e or f x raises e.

  • parameter on

    if provided, f runs on the given runner

val bind : ?on:Runner.t -> f:('a -> 'b t) -> 'a t -> 'b t

bind ?on ~f fut returns a new future fut2 that resolves like the future f x if fut resolved with x; and fails with e if fut fails with e or f x raises e.

  • parameter on

    if provided, f runs on the given runner

val bind_reify_error : ?on:Runner.t -> f:('a or_error -> 'b t) -> 'a t -> 'b t

bind_reify_error ?on ~f fut returns a new future fut2 that resolves like the future f (Ok x) if fut resolved with x; and resolves like the future f (Error (exn, bt)) if fut fails with exn and backtrace bt.

  • parameter on

    if provided, f runs on the given runner

  • since 0.4
val join : 'a t t -> 'a t

join fut is fut >>= Fun.id. It joins the inner layer of the future.

  • since 0.2
val both : 'a t -> 'b t -> ('a * 'b) t

both a b succeeds with x, y if a succeeds with x and b succeeds with y, or fails if any of them fails.

val choose : 'a t -> 'b t -> ('a, 'b) Either.t t

choose a b succeeds Left x or Right y if a succeeds with x or b succeeds with y, or fails if both of them fails. If they both succeed, it is not specified which result is used.

val choose_same : 'a t -> 'a t -> 'a t

choose_same a b succeeds with the value of one of a or b if they succeed, or fails if both fail. If they both succeed, it is not specified which result is used.

val join_array : 'a t array -> 'a array t

Wait for all the futures in the array. Fails if any future fails.

val join_list : 'a t list -> 'a list t

Wait for all the futures in the list. Fails if any future fails.

module Advanced : sig ... end
val map_list : f:('a -> 'b t) -> 'a list -> 'b list t

map_list ~f l is like join_list @@ List.map f l.

  • since 0.5.1
val wait_array : _ t array -> unit t

wait_array arr waits for all futures in arr to resolve. It discards the individual results of futures in arr. It fails if any future fails.

val wait_list : _ t list -> unit t

wait_list l waits for all futures in l to resolve. It discards the individual results of futures in l. It fails if any future fails.

val for_ : on:Runner.t -> int -> (int -> unit) -> unit t

for_ ~on n f runs f 0, f 1, …, f (n-1) on the runner, and returns a future that resolves when all the tasks have resolved, or fails as soon as one task has failed.

val for_array : on:Runner.t -> 'a array -> (int -> 'a -> unit) -> unit t

for_array ~on arr f runs f 0 arr.(0), …, f (n-1) arr.(n-1) in the runner (where n = Array.length arr), and returns a future that resolves when all the tasks are done, or fails if any of them fails.

  • since 0.2
val for_list : on:Runner.t -> 'a list -> ('a -> unit) -> unit t

for_list ~on l f is like for_array ~on (Array.of_list l) f.

  • since 0.2

Await

NOTE This is only available on OCaml 5.

val await : 'a t -> 'a

await fut suspends the current tasks until fut is fulfilled, then resumes the task on this same runner (but possibly on a different thread/domain).

  • since 0.3

This must only be run from inside the runner itself. The runner must support Suspend_. NOTE: only on OCaml 5.x

Blocking

val wait_block : 'a t -> 'a or_error

wait_block fut blocks the current thread until fut is resolved, and returns its value.

NOTE: A word of warning: this will monopolize the calling thread until the future resolves. This can also easily cause deadlocks, if enough threads in a pool call wait_block on futures running on the same pool or a pool depending on it.

A good rule to avoid deadlocks is to run this from outside of any pool, or to have an acyclic order between pools where wait_block is only called from a pool on futures evaluated in a pool that comes lower in the hierarchy. If this rule is broken, it is possible for all threads in a pool to wait for futures that can only make progress on these same threads, hence the deadlock.

val wait_block_exn : 'a t -> 'a

Same as wait_block but re-raises the exception if the future failed.

Infix operators

These combinators run on either the current pool (if present), or on the same thread that just fulfilled the previous future if not.

They were previously present as module Infix_local and val infix, but are now simplified.

  • since 0.5
module Infix : sig ... end
include module type of Infix
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
val (let+) : 'a t -> ('a -> 'b) -> 'b t
val (and+) : 'a t -> 'b t -> ('a * 'b) t
val (let*) : 'a t -> ('a -> 'b t) -> 'b t
val (and*) : 'a t -> 'b t -> ('a * 'b) t
module Infix_local = Infix
+Fut (moonpool.Moonpool.Fut)

Module Moonpool.Fut

Futures.

A future of type 'a t represents the result of a computation that will yield a value of type 'a.

Typically, the computation is running on a thread pool Runner.t and will proceed on some worker. Once set, a future cannot change. It either succeeds (storing a Ok x with x: 'a), or fail (storing a Error (exn, bt) with an exception and the corresponding backtrace).

Using spawn, it's possible to start a bunch of tasks, obtaining futures, and then use await to get their result in the desired order.

Combinators such as map and join_array can be used to produce futures from other futures (in a monadic way). Some combinators take a on argument to specify a runner on which the intermediate computation takes place; for example map ~on:pool ~f fut maps the value in fut using function f, applicatively; the call to f happens on the runner pool (once fut resolves successfully with a value). Be aware that these combinators do not preserve local storage.

type 'a or_error = ('a, Exn_bt.t) result
type 'a t = 'a Picos.Computation.t

A future with a result of type 'a.

type 'a promise = private 'a t

A promise, which can be fulfilled exactly once to set the corresponding future. This is a private alias of 'a t since 0.7, previously it was opaque.

val make : unit -> 'a t * 'a promise

Make a new future with the associated promise.

val make_promise : unit -> 'a promise

Same as make but returns a single promise (which can be upcast to a future). This is useful mostly to preserve memory, you probably don't need it.

How to upcast to a future in the worst case:

  let prom = Fut.make_promise ()
+  let fut = (prom : _ Fut.promise :> _ Fut.t)
  • since 0.7
val on_result : 'a t -> ('a or_error -> unit) -> unit

on_result fut f registers f to be called in the future when fut is set; or calls f immediately if fut is already set.

NOTE: it's ill advised to do meaningful work inside the callback f. Instead, try to spawn another task on the runner, or use await.

val on_result_ignore : _ t -> (Exn_bt.t option -> unit) -> unit

on_result_ignore fut f registers f to be called in the future when fut is set; or calls f immediately if fut is already set. It does not pass the result, only a success/error signal.

  • since 0.7
exception Already_fulfilled
val try_cancel : _ promise -> Exn_bt.t -> bool

try_cancel promise ebt tries to cancel the promise using the given exception, returning true. It returns false if the promise is already resolved.

  • since 0.9
val cancel : _ promise -> Exn_bt.t -> unit

Silent version of try_cancel, ignoring the result.

  • since 0.9
val fulfill : 'a promise -> 'a or_error -> unit

Fullfill the promise, setting the future at the same time.

val fulfill_idempotent : 'a promise -> 'a or_error -> unit

Fullfill the promise, setting the future at the same time. Does nothing if the promise is already fulfilled.

val return : 'a -> 'a t

Already settled future, with a result

val fail : exn -> Stdlib.Printexc.raw_backtrace -> _ t

Already settled future, with a failure

val fail_exn_bt : Exn_bt.t -> _ t

Fail from a bundle of exception and backtrace

  • since 0.6
val of_result : 'a or_error -> 'a t

Already resolved future from a result.

val is_resolved : _ t -> bool

is_resolved fut is true iff fut is resolved.

val peek : 'a t -> 'a or_error option

peek fut returns Some r if fut is currently resolved with r, and None if fut is not resolved yet.

exception Not_ready
  • since 0.2
val get_or_fail : 'a t -> 'a or_error

get_or_fail fut obtains the result from fut if it's fulfilled (i.e. if peek fut returns Some res, get_or_fail fut returns res).

  • since 0.2
val get_or_fail_exn : 'a t -> 'a

get_or_fail_exn fut obtains the result from fut if it's fulfilled, like get_or_fail. If the result is an Error _, the exception inside is re-raised.

  • since 0.2
val is_done : _ t -> bool

Is the future resolved? This is the same as peek fut |> Option.is_some.

  • since 0.2
val is_success : _ t -> bool

Checks if the future is resolved with Ok _ as a result.

  • since 0.6
val is_failed : _ t -> bool

Checks if the future is resolved with Error _ as a result.

  • since 0.6
val raise_if_failed : _ t -> unit

raise_if_failed fut raises e if fut failed with e.

  • since 0.6

Combinators

val spawn : on:Runner.t -> (unit -> 'a) -> 'a t

spaw ~on f runs f() on the given runner on, and return a future that will hold its result.

val spawn_on_current_runner : (unit -> 'a) -> 'a t

This must be run from inside a runner, and schedules the new task on it as well.

See Runner.get_current_runner to see how the runner is found.

  • since 0.5
  • raises Failure

    if run from outside a runner.

val reify_error : 'a t -> 'a or_error t

reify_error fut turns a failing future into a non-failing one that contain Error (exn, bt). A non-failing future returning x is turned into Ok x.

  • since 0.4
val map : ?on:Runner.t -> f:('a -> 'b) -> 'a t -> 'b t

map ?on ~f fut returns a new future fut2 that resolves with f x if fut resolved with x; and fails with e if fut fails with e or f x raises e.

  • parameter on

    if provided, f runs on the given runner

val bind : ?on:Runner.t -> f:('a -> 'b t) -> 'a t -> 'b t

bind ?on ~f fut returns a new future fut2 that resolves like the future f x if fut resolved with x; and fails with e if fut fails with e or f x raises e.

This does not preserve local storage of fut inside f.

  • parameter on

    if provided, f runs on the given runner

val bind_reify_error : ?on:Runner.t -> f:('a or_error -> 'b t) -> 'a t -> 'b t

bind_reify_error ?on ~f fut returns a new future fut2 that resolves like the future f (Ok x) if fut resolved with x; and resolves like the future f (Error (exn, bt)) if fut fails with exn and backtrace bt.

This does not preserve local storage of fut inside f.

  • parameter on

    if provided, f runs on the given runner

  • since 0.4
val join : 'a t t -> 'a t

join fut is fut >>= Fun.id. It joins the inner layer of the future.

  • since 0.2
val both : 'a t -> 'b t -> ('a * 'b) t

both a b succeeds with x, y if a succeeds with x and b succeeds with y, or fails if any of them fails.

val choose : 'a t -> 'b t -> ('a, 'b) Either.t t

choose a b succeeds Left x or Right y if a succeeds with x or b succeeds with y, or fails if both of them fails. If they both succeed, it is not specified which result is used.

val choose_same : 'a t -> 'a t -> 'a t

choose_same a b succeeds with the value of one of a or b if they succeed, or fails if both fail. If they both succeed, it is not specified which result is used.

val join_array : 'a t array -> 'a array t

Wait for all the futures in the array. Fails if any future fails.

val join_list : 'a t list -> 'a list t

Wait for all the futures in the list. Fails if any future fails.

module Advanced : sig ... end

Advanced primitives for synchronization

val map_list : f:('a -> 'b t) -> 'a list -> 'b list t

map_list ~f l is like join_list @@ List.map f l.

  • since 0.5.1
val wait_array : _ t array -> unit t

wait_array arr waits for all futures in arr to resolve. It discards the individual results of futures in arr. It fails if any future fails.

val wait_list : _ t list -> unit t

wait_list l waits for all futures in l to resolve. It discards the individual results of futures in l. It fails if any future fails.

val for_ : on:Runner.t -> int -> (int -> unit) -> unit t

for_ ~on n f runs f 0, f 1, …, f (n-1) on the runner, and returns a future that resolves when all the tasks have resolved, or fails as soon as one task has failed.

val for_array : on:Runner.t -> 'a array -> (int -> 'a -> unit) -> unit t

for_array ~on arr f runs f 0 arr.(0), …, f (n-1) arr.(n-1) in the runner (where n = Array.length arr), and returns a future that resolves when all the tasks are done, or fails if any of them fails.

  • since 0.2
val for_list : on:Runner.t -> 'a list -> ('a -> unit) -> unit t

for_list ~on l f is like for_array ~on (Array.of_list l) f.

  • since 0.2

Await

This suspends the current task using an OCaml 5 algebraic effect, and makes preparations for the task to be resumed once the future has been resolved.

val await : 'a t -> 'a

await fut suspends the current tasks until fut is fulfilled, then resumes the task on this same runner (but possibly on a different thread/domain).

  • since 0.3

This must only be run from inside the runner itself. The runner must support Suspend_.

val yield : unit -> unit

Like Moonpool.yield.

  • since NEXT_RELEASE

Blocking

val wait_block : 'a t -> 'a or_error

wait_block fut blocks the current thread until fut is resolved, and returns its value.

NOTE: A word of warning: this will monopolize the calling thread until the future resolves. This can also easily cause deadlocks, if enough threads in a pool call wait_block on futures running on the same pool or a pool depending on it.

A good rule to avoid deadlocks is to run this from outside of any pool, or to have an acyclic order between pools where wait_block is only called from a pool on futures evaluated in a pool that comes lower in the hierarchy. If this rule is broken, it is possible for all threads in a pool to wait for futures that can only make progress on these same threads, hence the deadlock.

val wait_block_exn : 'a t -> 'a

Same as wait_block but re-raises the exception if the future failed.

NOTE: do check the cautionary note in wait_block concerning deadlocks.

Infix operators

These combinators run on either the current pool (if present), or on the same thread that just fulfilled the previous future if not.

They were previously present as module Infix_local and val infix, but are now simplified.

  • since 0.5
module Infix : sig ... end
include module type of Infix
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
val (let+) : 'a t -> ('a -> 'b) -> 'b t
val (and+) : 'a t -> 'b t -> ('a * 'b) t
val (let*) : 'a t -> ('a -> 'b t) -> 'b t
val (and*) : 'a t -> 'b t -> ('a * 'b) t
module Infix_local = Infix
diff --git a/moonpool/Moonpool/Immediate_runner/index.html b/moonpool/Moonpool/Immediate_runner/index.html index 9b225e9d..d360ac28 100644 --- a/moonpool/Moonpool/Immediate_runner/index.html +++ b/moonpool/Moonpool/Immediate_runner/index.html @@ -1,2 +1,2 @@ -Immediate_runner (moonpool.Moonpool.Immediate_runner)

Module Moonpool.Immediate_runner

Runner that runs tasks in the caller thread.

This is removed since 0.6, and replaced by Moonpool_fib.Main.

  • deprecated use Moonpool_fib.Main
+Immediate_runner (moonpool.Moonpool.Immediate_runner)

Module Moonpool.Immediate_runner

Runner that runs tasks in the caller thread.

This is removed since 0.6, and replaced by Moonpool_fib.Main.

  • deprecated use Moonpool_fib.Main
diff --git a/moonpool/Moonpool/Main/index.html b/moonpool/Moonpool/Main/index.html new file mode 100644 index 00000000..d68343eb --- /dev/null +++ b/moonpool/Moonpool/Main/index.html @@ -0,0 +1,2 @@ + +Main (moonpool.Moonpool.Main)

Module Moonpool.Main

Main thread.

This is evolved from Moonpool.Immediate_runner, but unlike it, this API assumes you run it in a thread (possibly the main thread) which will block until the initial computation is done.

This means it's reasonable to use Main.main (fun () -> do_everything) at the beginning of the program. Other Moonpool pools can be created for background tasks, etc. to do the heavy lifting, and the main thread (inside this immediate runner) can coordinate tasks via Fiber.await.

Aside from the fact that this blocks the caller thread, it is fairly similar to Background_thread in that there's a single worker to process tasks/fibers.

This handles the concurency effects used in moonpool, including await and yield.

This module was migrated from the late Moonpool_fib.

  • since NEXT_RELEASE
val main : (Runner.t -> 'a) -> 'a

main f runs f() in a scope that handles effects, including Fiber.await.

This scope can run background tasks as well, in a cooperative fashion.

val main' : ?block_signals:bool -> unit -> (Runner.t -> 'a) -> 'a

Same as main but with room for optional arguments.

diff --git a/moonpool/Moonpool/Ws_pool/index.html b/moonpool/Moonpool/Ws_pool/index.html index 4a2a72ec..33ee87fe 100644 --- a/moonpool/Moonpool/Ws_pool/index.html +++ b/moonpool/Moonpool/Ws_pool/index.html @@ -3,7 +3,6 @@ ?on_init_thread:(dom_id:int -> t_id:int -> unit -> unit) -> ?on_exit_thread:(dom_id:int -> t_id:int -> unit -> unit) -> ?on_exn:(exn -> Stdlib.Printexc.raw_backtrace -> unit) -> - ?around_task:((t -> 'b) * (t -> 'b -> unit)) -> ?num_threads:int -> ?name:string -> - 'a

Arguments used in create. See create for explanations.

val create : (unit -> t, _) create_args

create () makes a new thread pool.

  • parameter on_init_thread

    called at the beginning of each new thread in the pool.

  • parameter num_threads

    size of the pool, ie. number of worker threads. It will be at least 1 internally, so 0 or negative values make no sense. The default is Domain.recommended_domain_count(), ie one worker thread per CPU core. On OCaml 4 the default is 4 (since there is only one domain).

  • parameter on_exit_thread

    called at the end of each thread in the pool

  • parameter around_task

    a pair of before, after, where before pool is called before a task is processed, on the worker thread about to run it, and returns x; and after pool x is called by the same thread after the task is over. (since 0.2)

  • parameter name

    a name for this thread pool, used if tracing is enabled (since 0.6)

val with_ : (unit -> (t -> 'a) -> 'a, _) create_args

with_ () f calls f pool, where pool is obtained via create. When f pool returns or fails, pool is shutdown and its resources are released.

Most parameters are the same as in create.

  • since 0.3
+ 'a

Arguments used in create. See create for explanations.

val create : (unit -> t, _) create_args

create () makes a new thread pool.

  • parameter on_init_thread

    called at the beginning of each new thread in the pool.

  • parameter num_threads

    size of the pool, ie. number of worker threads. It will be at least 1 internally, so 0 or negative values make no sense. The default is Domain.recommended_domain_count(), ie one worker thread per CPU core. On OCaml 4 the default is 4 (since there is only one domain).

  • parameter on_exit_thread

    called at the end of each thread in the pool

  • parameter name

    a name for this thread pool, used if tracing is enabled (since 0.6)

val with_ : (unit -> (t -> 'a) -> 'a, _) create_args

with_ () f calls f pool, where pool is obtained via create. When f pool returns or fails, pool is shutdown and its resources are released.

Most parameters are the same as in create.

  • since 0.3
diff --git a/moonpool/Moonpool/index.html b/moonpool/Moonpool/index.html index 9c345a04..772836ce 100644 --- a/moonpool/Moonpool/index.html +++ b/moonpool/Moonpool/index.html @@ -1,2 +1,2 @@ -Moonpool (moonpool.Moonpool)

Module Moonpool

Moonpool

A pool within a bigger pool (ie the ocean). Here, we're talking about pools of Thread.t that are dispatched over several Domain.t to enable parallelism.

We provide several implementations of pools with distinct scheduling strategies, alongside some concurrency primitives such as guarding locks (Lock.t) and futures (Fut.t).

module Ws_pool : sig ... end

Work-stealing thread pool.

module Fifo_pool : sig ... end

A simple thread pool in FIFO order.

module Background_thread : sig ... end

A simple runner with a single background thread.

module Runner : sig ... end

Interface for runners.

module Trigger : sig ... end

Triggers from picos

module Immediate_runner : sig ... end

Runner that runs tasks in the caller thread.

module Exn_bt : sig ... end

Exception with backtrace.

exception Shutdown

Exception raised when trying to run tasks on runners that have been shut down.

  • since 0.6
val start_thread_on_some_domain : ('a -> unit) -> 'a -> Thread.t

Similar to Thread.create, but it picks a background domain at random to run the thread. This ensures that we don't always pick the same domain to run all the various threads needed in an application (timers, event loops, etc.)

val run_async : ?fiber:Picos.Fiber.t -> Runner.t -> (unit -> unit) -> unit

run_async runner task schedules the task to run on the given runner. This means task() will be executed at some point in the future, possibly in another thread.

  • parameter fiber

    optional initial (picos) fiber state

  • since 0.5
val run_wait_block : ?fiber:Picos.Fiber.t -> Runner.t -> (unit -> 'a) -> 'a

run_wait_block runner f schedules f for later execution on the runner, like run_async. It then blocks the current thread until f() is done executing, and returns its result. If f() raises an exception, then run_wait_block pool f will raise it as well.

See run_async for more details.

NOTE be careful with deadlocks (see notes in Fut.wait_block about the required discipline to avoid deadlocks).

  • raises Shutdown

    if the runner was already shut down

  • since 0.6

Number of threads recommended to saturate the CPU. For IO pools this makes little sense (you might want more threads than this because many of them will be blocked most of the time).

  • since 0.5
val spawn : on:Runner.t -> (unit -> 'a) -> 'a Fut.t

spawn ~on f runs f() on the runner (a thread pool typically) and returns a future result for it. See Fut.spawn.

  • since 0.5
val spawn_on_current_runner : (unit -> 'a) -> 'a Fut.t
val get_current_runner : unit -> Runner.t option
val await : 'a Fut.t -> 'a

Await a future, must be run on a moonpool runner. See Await. Only on OCaml >= 5.0.

  • since 0.5
val yield : unit -> unit

Yield from the current task, must be run on a moonpool runner. Only on OCaml >= 5.0.

  • since NEXT_RELEASE
module Lock : sig ... end

Mutex-protected resource.

module Fut : sig ... end

Futures.

module Chan : sig ... end

Channels.

module Task_local_storage : sig ... end

Task-local storage.

module Thread_local_storage = Thread_local_storage
module Blocking_queue : sig ... end

A simple blocking queue.

module Atomic = Stdlib.Atomic

Atomic values.

+Moonpool (moonpool.Moonpool)

Module Moonpool

Moonpool

A pool within a bigger pool (ie the ocean). Here, we're talking about pools of Thread.t that are dispatched over several Domain.t to enable parallelism.

We provide several implementations of pools with distinct scheduling strategies, alongside some concurrency primitives such as guarding locks (Lock.t) and futures (Fut.t).

module Ws_pool : sig ... end

Work-stealing thread pool.

module Fifo_pool : sig ... end

A simple thread pool in FIFO order.

module Background_thread : sig ... end

A simple runner with a single background thread.

module Runner : sig ... end

Interface for runners.

module Trigger : sig ... end

Triggers from picos

module Main : sig ... end

Main thread.

module Immediate_runner : sig ... end

Runner that runs tasks in the caller thread.

module Exn_bt : sig ... end

Exception with backtrace.

exception Shutdown

Exception raised when trying to run tasks on runners that have been shut down.

  • since 0.6
val start_thread_on_some_domain : ('a -> unit) -> 'a -> Thread.t

Similar to Thread.create, but it picks a background domain at random to run the thread. This ensures that we don't always pick the same domain to run all the various threads needed in an application (timers, event loops, etc.)

val run_async : ?fiber:Picos.Fiber.t -> Runner.t -> (unit -> unit) -> unit

run_async runner task schedules the task to run on the given runner. This means task() will be executed at some point in the future, possibly in another thread.

  • parameter fiber

    optional initial (picos) fiber state

  • since 0.5
val run_wait_block : ?fiber:Picos.Fiber.t -> Runner.t -> (unit -> 'a) -> 'a

run_wait_block runner f schedules f for later execution on the runner, like run_async. It then blocks the current thread until f() is done executing, and returns its result. If f() raises an exception, then run_wait_block pool f will raise it as well.

See run_async for more details.

NOTE be careful with deadlocks (see notes in Fut.wait_block about the required discipline to avoid deadlocks).

  • raises Shutdown

    if the runner was already shut down

  • since 0.6

Number of threads recommended to saturate the CPU. For IO pools this makes little sense (you might want more threads than this because many of them will be blocked most of the time).

  • since 0.5
val spawn : on:Runner.t -> (unit -> 'a) -> 'a Fut.t

spawn ~on f runs f() on the runner (a thread pool typically) and returns a future result for it. See Fut.spawn.

  • since 0.5
val spawn_on_current_runner : (unit -> 'a) -> 'a Fut.t
val get_current_runner : unit -> Runner.t option
val await : 'a Fut.t -> 'a

Await a future, must be run on a moonpool runner. See Await. Only on OCaml >= 5.0.

  • since 0.5
val yield : unit -> unit

Yield from the current task, must be run on a moonpool runner. Only on OCaml >= 5.0.

  • since 0.9
module Lock : sig ... end

Mutex-protected resource.

module Fut : sig ... end

Futures.

module Chan : sig ... end

Channels.

module Task_local_storage : sig ... end

Task-local storage.

module Thread_local_storage = Thread_local_storage
module Blocking_queue : sig ... end

A simple blocking queue.

module Atomic = Stdlib.Atomic

Atomic values.

include module type of struct include Main end
val main : (Runner.t -> 'a) -> 'a

main f runs f() in a scope that handles effects, including Fiber.await.

This scope can run background tasks as well, in a cooperative fashion.

val main' : ?block_signals:bool -> unit -> (Runner.t -> 'a) -> 'a

Same as main but with room for optional arguments.

diff --git a/moonpool/Moonpool_fib__/index.html b/moonpool/Moonpool__Main/index.html similarity index 75% rename from moonpool/Moonpool_fib__/index.html rename to moonpool/Moonpool__Main/index.html index c71cae14..a75ff1af 100644 --- a/moonpool/Moonpool_fib__/index.html +++ b/moonpool/Moonpool__Main/index.html @@ -1,2 +1,2 @@ -Moonpool_fib__ (moonpool.Moonpool_fib__)

Module Moonpool_fib__

This module is hidden.

+Moonpool__Main (moonpool.Moonpool__Main)

Module Moonpool__Main

This module is hidden.

diff --git a/moonpool/Moonpool_fib/Fiber/index.html b/moonpool/Moonpool_fib/Fiber/index.html deleted file mode 100644 index 5de1e2aa..00000000 --- a/moonpool/Moonpool_fib/Fiber/index.html +++ /dev/null @@ -1,6 +0,0 @@ - -Fiber (moonpool.Moonpool_fib.Fiber)

Module Moonpool_fib.Fiber

Fibers.

A fiber is a lightweight computation that runs cooperatively alongside other fibers. In the context of moonpool, fibers have additional properties:

type cancel_callback = Moonpool.Exn_bt.t -> unit

A callback used in case of cancellation

type 'a t

A fiber returning a value of type 'a.

val res : 'a t -> 'a Moonpool.Fut.t

Future result of the fiber.

type 'a callback = 'a Moonpool.Exn_bt.result -> unit

Callbacks that are called when a fiber is done.

type any =
  1. | Any : _ t -> any

Type erased fiber

val return : 'a -> 'a t
val fail : Moonpool.Exn_bt.t -> _ t
val self : unit -> any

self () is the current fiber. Must be run from inside a fiber.

  • raises Failure

    if not run from inside a fiber.

val peek : 'a t -> 'a Moonpool.Fut.or_error option

Peek inside the future result

val is_done : _ t -> bool

Has the fiber completed?

val is_cancelled : _ t -> bool

Has the fiber completed with a failure?

val is_success : _ t -> bool

Has the fiber completed with a value?

val await : 'a t -> 'a

await fib is like Fut.await (res fib)

val wait_block_exn : 'a t -> 'a

wait_block_exn fib is Fut.wait_block_exn (res fib). NOTE: See Fut.wait_block for warnings about deadlocks.

val wait_block : 'a t -> 'a Moonpool.Fut.or_error

wait_block fib is Fut.wait_block (res fib). NOTE: See Fut.wait_block for warnings about deadlocks.

val check_if_cancelled : unit -> unit

Check if the current fiber is cancelled, in which case this raises. Must be run from inside a fiber.

  • raises e

    if the current fiber is cancelled with exception e

  • raises Failure

    if not run from a fiber.

val yield : unit -> unit

Yield control to the scheduler from the current fiber.

  • raises Failure

    if not run from inside a fiber.

type cancel_handle

An opaque handle for a single cancel callback in a fiber

val add_on_cancel : _ t -> cancel_callback -> cancel_handle

add_on_cancel fib cb adds cb to the list of cancel callbacks for fib. If fib is already cancelled, cb is called immediately.

val remove_on_cancel : _ t -> cancel_handle -> unit

remove_on_cancel fib h removes the cancel callback associated with handle h.

val with_on_cancel : _ t -> cancel_callback -> (unit -> 'a) -> 'a

with_on_cancel fib cb (fun () -> <e>) evaluates e in a scope in which, if the fiber fib is cancelled, cb() is called. If e returns without the fiber being cancelled, this callback is removed.

val with_on_self_cancel : cancel_callback -> (unit -> 'a) -> 'a

with_on_self_cancel cb f calls f() in a scope where cb is added to the cancel callbacks of the current fiber; and f() terminates, cb is removed from the list.

val on_result : 'a t -> 'a callback -> unit

Wait for fiber to be done and call the callback with the result. If the fiber is done already then the callback is invoked immediately with its result.

val spawn_top : on:Moonpool.Runner.t -> (unit -> 'a) -> 'a t

spawn_top ~on f spawns a new (toplevel) fiber onto the given runner. This fiber is not the child of any other fiber: its lifetime is only determined by the lifetime of f().

val spawn : ?on:Moonpool.Runner.t -> ?protect:bool -> (unit -> 'a) -> 'a t

spawn ~protect f spawns a sub-fiber f_child from a running fiber parent. The sub-fiber f_child is attached to the current fiber and fails if the current fiber parent fails.

  • parameter on

    if provided, start the fiber on the given runner. If not provided, use the parent's runner.

  • parameter protect

    if true, when f_child fails, it does not affect parent. If false, f_child failing also causes parent to fail (and therefore all other children of parent). Default is true.

Must be run from inside a fiber.

  • raises Failure

    if not run from inside a fiber.

val spawn_ignore : - ?on:Moonpool.Runner.t -> - ?protect:bool -> - (unit -> _) -> - unit

spawn_ignore f is ignore (spawn f). The fiber will still affect termination of the parent, ie. the parent will exit only after this new fiber exits.

  • parameter on

    the optional runner to use, added since 0.7

val spawn_top_ignore : on:Moonpool.Runner.t -> (unit -> _) -> unit

Like spawn_top but ignores the result.

  • since 0.7
diff --git a/moonpool/Moonpool_fib/Fls/index.html b/moonpool/Moonpool_fib/Fls/index.html deleted file mode 100644 index f24f6a86..00000000 --- a/moonpool/Moonpool_fib/Fls/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Fls (moonpool.Moonpool_fib.Fls)

Module Moonpool_fib.Fls

Fiber-local storage.

This storage is associated to the current fiber, just like thread-local storage is associated with the current thread.

See Moonpool.Task_local_storage for more general information, as this is based on it.

NOTE: it's important to note that, while each fiber has its own storage, spawning a sub-fiber f2 from a fiber f1 will only do a shallow copy of the storage. Values inside f1's storage will be physically shared with f2. It is thus recommended to store only persistent values in the local storage.

include module type of struct include Moonpool.Task_local_storage end
type 'a t = 'a Picos.Fiber.FLS.t
val create : unit -> 'a t

create () makes a new key. Keys are expensive and should never be allocated dynamically or in a loop.

exception Not_set
val get_exn : 'a t -> 'a

get k gets the value for the current task for key k. Must be run from inside a task running on a runner.

val get_opt : 'a t -> 'a option

get_opt k gets the current task's value for key k, or None if not run from inside the task.

val get : 'a t -> default:'a -> 'a
val set : 'a t -> 'a -> unit

set k v sets the storage for k to v. Must be run from inside a task running on a runner.

  • raises Failure

    otherwise

val with_value : 'a t -> 'a -> (unit -> 'b) -> 'b

with_value k v f sets k to v for the duration of the call to f(). When f() returns (or fails), k is restored to its old value.

Local Hmap.t

This requires hmap to be installed.

val k_local_hmap : Hmap.t Picos.Fiber.FLS.t

A local hmap, inherited in children fibers

val get_local_hmap : unit -> Hmap.t

Access the local hmap, or an empty one if not set

val set_local_hmap : Hmap.t -> unit
val update_local_hmap : (Hmap.t -> Hmap.t) -> unit
val get_in_local_hmap_exn : 'a Hmap.key -> 'a
  • raises Invalid_argument

    if not present

val get_in_local_hmap_opt : 'a Hmap.key -> 'a option
val remove_in_local_hmap : 'a Hmap.key -> unit

Remove given key from the local hmap

val set_in_local_hmap : 'a Hmap.key -> 'a -> unit
val with_in_local_hmap : 'a Hmap.key -> 'a -> (unit -> 'b) -> 'b

with_in_local_hmap k v f calls f() in a context where k is bound to v in the local hmap. Then it restores the previous binding for k.

diff --git a/moonpool/Moonpool_fib/Handle/Map/index.html b/moonpool/Moonpool_fib/Handle/Map/index.html deleted file mode 100644 index 1bbd1c67..00000000 --- a/moonpool/Moonpool_fib/Handle/Map/index.html +++ /dev/null @@ -1,8 +0,0 @@ - -Map (moonpool.Moonpool_fib.Handle.Map)

Module Handle.Map

Maps

type key = t

The type of the map keys.

type !+'a t

The type of maps from type key to type 'a.

val empty : 'a t

The empty map.

val add : key -> 'a -> 'a t -> 'a t

add key data m returns a map containing the same bindings as m, plus a binding of key to data. If key was already bound in m to a value that is physically equal to data, m is returned unchanged (the result of the function is then physically equal to m). Otherwise, the previous binding of key in m disappears.

  • before 4.03

    Physical equality was not ensured.

val add_to_list : key -> 'a -> 'a list t -> 'a list t

add_to_list key data m is m with key mapped to l such that l is data :: Map.find key m if key was bound in m and [v] otherwise.

  • since 5.1
val update : key -> ('a option -> 'a option) -> 'a t -> 'a t

update key f m returns a map containing the same bindings as m, except for the binding of key. Depending on the value of y where y is f (find_opt key m), the binding of key is added, removed or updated. If y is None, the binding is removed if it exists; otherwise, if y is Some z then key is associated to z in the resulting map. If key was already bound in m to a value that is physically equal to z, m is returned unchanged (the result of the function is then physically equal to m).

  • since 4.06
val singleton : key -> 'a -> 'a t

singleton x y returns the one-element map that contains a binding y for x.

  • since 3.12
val remove : key -> 'a t -> 'a t

remove x m returns a map containing the same bindings as m, except for x which is unbound in the returned map. If x was not in m, m is returned unchanged (the result of the function is then physically equal to m).

  • before 4.03

    Physical equality was not ensured.

val merge : - (key -> 'a option -> 'b option -> 'c option) -> - 'a t -> - 'b t -> - 'c t

merge f m1 m2 computes a map whose keys are a subset of the keys of m1 and of m2. The presence of each such binding, and the corresponding value, is determined with the function f. In terms of the find_opt operation, we have find_opt x (merge f m1 m2) = f x (find_opt x m1) (find_opt x m2) for any key x, provided that f x None None = None.

  • since 3.12
val union : (key -> 'a -> 'a -> 'a option) -> 'a t -> 'a t -> 'a t

union f m1 m2 computes a map whose keys are a subset of the keys of m1 and of m2. When the same binding is defined in both arguments, the function f is used to combine them. This is a special case of merge: union f m1 m2 is equivalent to merge f' m1 m2, where

  • f' _key None None = None
  • f' _key (Some v) None = Some v
  • f' _key None (Some v) = Some v
  • f' key (Some v1) (Some v2) = f key v1 v2
  • since 4.03
val cardinal : 'a t -> int

Return the number of bindings of a map.

  • since 3.12

Bindings

val bindings : 'a t -> (key * 'a) list

Return the list of all bindings of the given map. The returned list is sorted in increasing order of keys with respect to the ordering Ord.compare, where Ord is the argument given to Map.Make.

  • since 3.12
val min_binding : 'a t -> key * 'a

Return the binding with the smallest key in a given map (with respect to the Ord.compare ordering), or raise Not_found if the map is empty.

  • since 3.12
val min_binding_opt : 'a t -> (key * 'a) option

Return the binding with the smallest key in the given map (with respect to the Ord.compare ordering), or None if the map is empty.

  • since 4.05
val max_binding : 'a t -> key * 'a

Same as min_binding, but returns the binding with the largest key in the given map.

  • since 3.12
val max_binding_opt : 'a t -> (key * 'a) option

Same as min_binding_opt, but returns the binding with the largest key in the given map.

  • since 4.05
val choose : 'a t -> key * 'a

Return one binding of the given map, or raise Not_found if the map is empty. Which binding is chosen is unspecified, but equal bindings will be chosen for equal maps.

  • since 3.12
val choose_opt : 'a t -> (key * 'a) option

Return one binding of the given map, or None if the map is empty. Which binding is chosen is unspecified, but equal bindings will be chosen for equal maps.

  • since 4.05

Searching

val find : key -> 'a t -> 'a

find x m returns the current value of x in m, or raises Not_found if no binding for x exists.

val find_opt : key -> 'a t -> 'a option

find_opt x m returns Some v if the current value of x in m is v, or None if no binding for x exists.

  • since 4.05
val find_first : (key -> bool) -> 'a t -> key * 'a

find_first f m, where f is a monotonically increasing function, returns the binding of m with the lowest key k such that f k, or raises Not_found if no such key exists.

For example, find_first (fun k -> Ord.compare k x >= 0) m will return the first binding k, v of m where Ord.compare k x >= 0 (intuitively: k >= x), or raise Not_found if x is greater than any element of m.

  • since 4.05
val find_first_opt : (key -> bool) -> 'a t -> (key * 'a) option

find_first_opt f m, where f is a monotonically increasing function, returns an option containing the binding of m with the lowest key k such that f k, or None if no such key exists.

  • since 4.05
val find_last : (key -> bool) -> 'a t -> key * 'a

find_last f m, where f is a monotonically decreasing function, returns the binding of m with the highest key k such that f k, or raises Not_found if no such key exists.

  • since 4.05
val find_last_opt : (key -> bool) -> 'a t -> (key * 'a) option

find_last_opt f m, where f is a monotonically decreasing function, returns an option containing the binding of m with the highest key k such that f k, or None if no such key exists.

  • since 4.05

Traversing

val iter : (key -> 'a -> unit) -> 'a t -> unit

iter f m applies f to all bindings in map m. f receives the key as first argument, and the associated value as second argument. The bindings are passed to f in increasing order with respect to the ordering over the type of the keys.

val fold : (key -> 'a -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

fold f m init computes (f kN dN ... (f k1 d1 init)...), where k1 ... kN are the keys of all bindings in m (in increasing order), and d1 ... dN are the associated data.

Transforming

val map : ('a -> 'b) -> 'a t -> 'b t

map f m returns a map with same domain as m, where the associated value a of all bindings of m has been replaced by the result of the application of f to a. The bindings are passed to f in increasing order with respect to the ordering over the type of the keys.

val mapi : (key -> 'a -> 'b) -> 'a t -> 'b t

Same as map, but the function receives as arguments both the key and the associated value for each binding of the map.

val filter : (key -> 'a -> bool) -> 'a t -> 'a t

filter f m returns the map with all the bindings in m that satisfy predicate p. If every binding in m satisfies f, m is returned unchanged (the result of the function is then physically equal to m)

  • since 3.12
  • before 4.03

    Physical equality was not ensured.

val filter_map : (key -> 'a -> 'b option) -> 'a t -> 'b t

filter_map f m applies the function f to every binding of m, and builds a map from the results. For each binding (k, v) in the input map:

  • if f k v is None then k is not in the result,
  • if f k v is Some v' then the binding (k, v') is in the output map.

For example, the following function on maps whose values are lists

filter_map
-  (fun _k li -> match li with [] -> None | _::tl -> Some tl)
-  m

drops all bindings of m whose value is an empty list, and pops the first element of each value that is non-empty.

  • since 4.11
val partition : (key -> 'a -> bool) -> 'a t -> 'a t * 'a t

partition f m returns a pair of maps (m1, m2), where m1 contains all the bindings of m that satisfy the predicate f, and m2 is the map with all the bindings of m that do not satisfy f.

  • since 3.12
val split : key -> 'a t -> 'a t * 'a option * 'a t

split x m returns a triple (l, data, r), where l is the map with all the bindings of m whose key is strictly less than x; r is the map with all the bindings of m whose key is strictly greater than x; data is None if m contains no binding for x, or Some v if m binds v to x.

  • since 3.12

Predicates and comparisons

val is_empty : 'a t -> bool

Test whether a map is empty or not.

val mem : key -> 'a t -> bool

mem x m returns true if m contains a binding for x, and false otherwise.

val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool

equal cmp m1 m2 tests whether the maps m1 and m2 are equal, that is, contain equal keys and associate them with equal data. cmp is the equality predicate used to compare the data associated with the keys.

val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int

Total ordering between maps. The first argument is a total ordering used to compare data associated with equal keys in the two maps.

val for_all : (key -> 'a -> bool) -> 'a t -> bool

for_all f m checks if all the bindings of the map satisfy the predicate f.

  • since 3.12
val exists : (key -> 'a -> bool) -> 'a t -> bool

exists f m checks if at least one binding of the map satisfies the predicate f.

  • since 3.12

Converting

val to_list : 'a t -> (key * 'a) list

to_list m is bindings m.

  • since 5.1
val of_list : (key * 'a) list -> 'a t

of_list bs adds the bindings of bs to the empty map, in list order (if a key is bound twice in bs the last one takes over).

  • since 5.1
val to_seq : 'a t -> (key * 'a) Seq.t

Iterate on the whole map, in ascending order of keys

  • since 4.07
val to_rev_seq : 'a t -> (key * 'a) Seq.t

Iterate on the whole map, in descending order of keys

  • since 4.12
val to_seq_from : key -> 'a t -> (key * 'a) Seq.t

to_seq_from k m iterates on a subset of the bindings of m, in ascending order of keys, from key k or above.

  • since 4.07
val add_seq : (key * 'a) Seq.t -> 'a t -> 'a t

Add the given bindings to the map, in order.

  • since 4.07
val of_seq : (key * 'a) Seq.t -> 'a t

Build a map from the given bindings

  • since 4.07
diff --git a/moonpool/Moonpool_fib/Handle/Set/index.html b/moonpool/Moonpool_fib/Handle/Set/index.html deleted file mode 100644 index 5f290ef5..00000000 --- a/moonpool/Moonpool_fib/Handle/Set/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Set (moonpool.Moonpool_fib.Handle.Set)

Module Handle.Set

Sets

type elt = t

The type of the set elements.

type t

The type of sets.

val empty : t

The empty set.

val add : elt -> t -> t

add x s returns a set containing all elements of s, plus x. If x was already in s, s is returned unchanged (the result of the function is then physically equal to s).

  • before 4.03

    Physical equality was not ensured.

val singleton : elt -> t

singleton x returns the one-element set containing only x.

val remove : elt -> t -> t

remove x s returns a set containing all elements of s, except x. If x was not in s, s is returned unchanged (the result of the function is then physically equal to s).

  • before 4.03

    Physical equality was not ensured.

val union : t -> t -> t

Set union.

val inter : t -> t -> t

Set intersection.

val disjoint : t -> t -> bool

Test if two sets are disjoint.

  • since 4.08
val diff : t -> t -> t

Set difference: diff s1 s2 contains the elements of s1 that are not in s2.

val cardinal : t -> int

Return the number of elements of a set.

Elements

val elements : t -> elt list

Return the list of all elements of the given set. The returned list is sorted in increasing order with respect to the ordering Ord.compare, where Ord is the argument given to Set.Make.

val min_elt : t -> elt

Return the smallest element of the given set (with respect to the Ord.compare ordering), or raise Not_found if the set is empty.

val min_elt_opt : t -> elt option

Return the smallest element of the given set (with respect to the Ord.compare ordering), or None if the set is empty.

  • since 4.05
val max_elt : t -> elt

Same as min_elt, but returns the largest element of the given set.

val max_elt_opt : t -> elt option

Same as min_elt_opt, but returns the largest element of the given set.

  • since 4.05
val choose : t -> elt

Return one element of the given set, or raise Not_found if the set is empty. Which element is chosen is unspecified, but equal elements will be chosen for equal sets.

val choose_opt : t -> elt option

Return one element of the given set, or None if the set is empty. Which element is chosen is unspecified, but equal elements will be chosen for equal sets.

  • since 4.05

Searching

val find : elt -> t -> elt

find x s returns the element of s equal to x (according to Ord.compare), or raise Not_found if no such element exists.

  • since 4.01
val find_opt : elt -> t -> elt option

find_opt x s returns the element of s equal to x (according to Ord.compare), or None if no such element exists.

  • since 4.05
val find_first : (elt -> bool) -> t -> elt

find_first f s, where f is a monotonically increasing function, returns the lowest element e of s such that f e, or raises Not_found if no such element exists.

For example, find_first (fun e -> Ord.compare e x >= 0) s will return the first element e of s where Ord.compare e x >= 0 (intuitively: e >= x), or raise Not_found if x is greater than any element of s.

  • since 4.05
val find_first_opt : (elt -> bool) -> t -> elt option

find_first_opt f s, where f is a monotonically increasing function, returns an option containing the lowest element e of s such that f e, or None if no such element exists.

  • since 4.05
val find_last : (elt -> bool) -> t -> elt

find_last f s, where f is a monotonically decreasing function, returns the highest element e of s such that f e, or raises Not_found if no such element exists.

  • since 4.05
val find_last_opt : (elt -> bool) -> t -> elt option

find_last_opt f s, where f is a monotonically decreasing function, returns an option containing the highest element e of s such that f e, or None if no such element exists.

  • since 4.05

Traversing

val iter : (elt -> unit) -> t -> unit

iter f s applies f in turn to all elements of s. The elements of s are presented to f in increasing order with respect to the ordering over the type of the elements.

val fold : (elt -> 'acc -> 'acc) -> t -> 'acc -> 'acc

fold f s init computes (f xN ... (f x2 (f x1 init))...), where x1 ... xN are the elements of s, in increasing order.

Transforming

val map : (elt -> elt) -> t -> t

map f s is the set whose elements are f a0,f a1... f aN, where a0,a1...aN are the elements of s.

The elements are passed to f in increasing order with respect to the ordering over the type of the elements.

If no element of s is changed by f, s is returned unchanged. (If each output of f is physically equal to its input, the returned set is physically equal to s.)

  • since 4.04
val filter : (elt -> bool) -> t -> t

filter f s returns the set of all elements in s that satisfy predicate f. If f satisfies every element in s, s is returned unchanged (the result of the function is then physically equal to s).

  • before 4.03

    Physical equality was not ensured.

val filter_map : (elt -> elt option) -> t -> t

filter_map f s returns the set of all v such that f x = Some v for some element x of s.

For example,

filter_map (fun n -> if n mod 2 = 0 then Some (n / 2) else None) s

is the set of halves of the even elements of s.

If no element of s is changed or dropped by f (if f x = Some x for each element x), then s is returned unchanged: the result of the function is then physically equal to s.

  • since 4.11
val partition : (elt -> bool) -> t -> t * t

partition f s returns a pair of sets (s1, s2), where s1 is the set of all the elements of s that satisfy the predicate f, and s2 is the set of all the elements of s that do not satisfy f.

val split : elt -> t -> t * bool * t

split x s returns a triple (l, present, r), where l is the set of elements of s that are strictly less than x; r is the set of elements of s that are strictly greater than x; present is false if s contains no element equal to x, or true if s contains an element equal to x.

Predicates and comparisons

val is_empty : t -> bool

Test whether a set is empty or not.

val mem : elt -> t -> bool

mem x s tests whether x belongs to the set s.

val equal : t -> t -> bool

equal s1 s2 tests whether the sets s1 and s2 are equal, that is, contain equal elements.

val compare : t -> t -> int

Total ordering between sets. Can be used as the ordering function for doing sets of sets.

val subset : t -> t -> bool

subset s1 s2 tests whether the set s1 is a subset of the set s2.

val for_all : (elt -> bool) -> t -> bool

for_all f s checks if all elements of the set satisfy the predicate f.

val exists : (elt -> bool) -> t -> bool

exists f s checks if at least one element of the set satisfies the predicate f.

Converting

val to_list : t -> elt list

to_list s is elements s.

  • since 5.1
val of_list : elt list -> t

of_list l creates a set from a list of elements. This is usually more efficient than folding add over the list, except perhaps for lists with many duplicated elements.

  • since 4.02
val to_seq_from : elt -> t -> elt Seq.t

to_seq_from x s iterates on a subset of the elements of s in ascending order, from x or above.

  • since 4.07
val to_seq : t -> elt Seq.t

Iterate on the whole set, in ascending order

  • since 4.07
val to_rev_seq : t -> elt Seq.t

Iterate on the whole set, in descending order

  • since 4.12
val add_seq : elt Seq.t -> t -> t

Add the given elements to the set, in order.

  • since 4.07
val of_seq : elt Seq.t -> t

Build a set from the given bindings

  • since 4.07
diff --git a/moonpool/Moonpool_fib/Handle/index.html b/moonpool/Moonpool_fib/Handle/index.html deleted file mode 100644 index 29f4b8ed..00000000 --- a/moonpool/Moonpool_fib/Handle/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Handle (moonpool.Moonpool_fib.Handle)

Module Moonpool_fib.Handle

The unique name of a fiber.

Each fiber has a unique handle that can be used to refer to it in maps or sets.

type t = private int

Unique, opaque identifier for a fiber.

val equal : t -> t -> bool
val compare : t -> t -> int
val hash : t -> int
val generate_fresh : unit -> t

Generate a fresh, unique identifier

module Set : Set.S with type elt = t
module Map : Map.S with type key = t
diff --git a/moonpool/Moonpool_fib/Main/index.html b/moonpool/Moonpool_fib/Main/index.html deleted file mode 100644 index b4d6ad87..00000000 --- a/moonpool/Moonpool_fib/Main/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Main (moonpool.Moonpool_fib.Main)

Module Moonpool_fib.Main

Main thread.

This is evolved from Moonpool.Immediate_runner, but unlike it, this API assumes you run it in a thread (possibly the main thread) which will block until the initial computation is done.

This means it's reasonable to use Main.main (fun () -> do_everything) at the beginning of the program. Other Moonpool pools can be created for background tasks, etc. to do the heavy lifting, and the main thread (inside this immediate runner) can coordinate tasks via Fiber.await.

Aside from the fact that this blocks the caller thread, it is fairly similar to Background_thread in that there's a single worker to process tasks/fibers.

This handles effects, including the ones in Fiber.

val main : (Moonpool.Runner.t -> 'a) -> 'a

main f runs f() in a scope that handles effects, including Fiber.await.

This scope can run background tasks as well, in a cooperative fashion.

val main' : ?block_signals:bool -> unit -> (Moonpool.Runner.t -> 'a) -> 'a

Same as main but with room for optional arguments.

  • since 0.7
diff --git a/moonpool/Moonpool_fib/index.html b/moonpool/Moonpool_fib/index.html deleted file mode 100644 index 73294979..00000000 --- a/moonpool/Moonpool_fib/index.html +++ /dev/null @@ -1,6 +0,0 @@ - -Moonpool_fib (moonpool.Moonpool_fib)

Module Moonpool_fib

Fibers for moonpool.

See Fiber for the most important explanations.

module Fiber : sig ... end

Fibers.

module Fls : sig ... end

Fiber-local storage.

module Handle : sig ... end

The unique name of a fiber.

module Main : sig ... end

Main thread.

include module type of struct include Fiber end
type cancel_callback = Moonpool.Exn_bt.t -> unit

A callback used in case of cancellation

type 'a t

A fiber returning a value of type 'a.

val res : 'a t -> 'a Moonpool.Fut.t

Future result of the fiber.

type 'a callback = 'a Moonpool.Exn_bt.result -> unit

Callbacks that are called when a fiber is done.

type any =
  1. | Any : _ t -> any

Type erased fiber

val return : 'a -> 'a t
val fail : Moonpool.Exn_bt.t -> _ t
val self : unit -> any

self () is the current fiber. Must be run from inside a fiber.

  • raises Failure

    if not run from inside a fiber.

val peek : 'a t -> 'a Moonpool.Fut.or_error option

Peek inside the future result

val is_done : _ t -> bool

Has the fiber completed?

val is_cancelled : _ t -> bool

Has the fiber completed with a failure?

val is_success : _ t -> bool

Has the fiber completed with a value?

val await : 'a t -> 'a

await fib is like Fut.await (res fib)

val wait_block_exn : 'a t -> 'a

wait_block_exn fib is Fut.wait_block_exn (res fib). NOTE: See Fut.wait_block for warnings about deadlocks.

val wait_block : 'a t -> 'a Moonpool.Fut.or_error

wait_block fib is Fut.wait_block (res fib). NOTE: See Fut.wait_block for warnings about deadlocks.

val check_if_cancelled : unit -> unit

Check if the current fiber is cancelled, in which case this raises. Must be run from inside a fiber.

  • raises e

    if the current fiber is cancelled with exception e

  • raises Failure

    if not run from a fiber.

val yield : unit -> unit

Yield control to the scheduler from the current fiber.

  • raises Failure

    if not run from inside a fiber.

type cancel_handle = Fiber.cancel_handle

An opaque handle for a single cancel callback in a fiber

val add_on_cancel : _ t -> cancel_callback -> cancel_handle

add_on_cancel fib cb adds cb to the list of cancel callbacks for fib. If fib is already cancelled, cb is called immediately.

val remove_on_cancel : _ t -> cancel_handle -> unit

remove_on_cancel fib h removes the cancel callback associated with handle h.

val with_on_cancel : _ t -> cancel_callback -> (unit -> 'a) -> 'a

with_on_cancel fib cb (fun () -> <e>) evaluates e in a scope in which, if the fiber fib is cancelled, cb() is called. If e returns without the fiber being cancelled, this callback is removed.

val with_on_self_cancel : cancel_callback -> (unit -> 'a) -> 'a

with_on_self_cancel cb f calls f() in a scope where cb is added to the cancel callbacks of the current fiber; and f() terminates, cb is removed from the list.

val on_result : 'a t -> 'a callback -> unit

Wait for fiber to be done and call the callback with the result. If the fiber is done already then the callback is invoked immediately with its result.

val spawn_top : on:Moonpool.Runner.t -> (unit -> 'a) -> 'a t

spawn_top ~on f spawns a new (toplevel) fiber onto the given runner. This fiber is not the child of any other fiber: its lifetime is only determined by the lifetime of f().

val spawn : ?on:Moonpool.Runner.t -> ?protect:bool -> (unit -> 'a) -> 'a t

spawn ~protect f spawns a sub-fiber f_child from a running fiber parent. The sub-fiber f_child is attached to the current fiber and fails if the current fiber parent fails.

  • parameter on

    if provided, start the fiber on the given runner. If not provided, use the parent's runner.

  • parameter protect

    if true, when f_child fails, it does not affect parent. If false, f_child failing also causes parent to fail (and therefore all other children of parent). Default is true.

Must be run from inside a fiber.

  • raises Failure

    if not run from inside a fiber.

val spawn_ignore : - ?on:Moonpool.Runner.t -> - ?protect:bool -> - (unit -> _) -> - unit

spawn_ignore f is ignore (spawn f). The fiber will still affect termination of the parent, ie. the parent will exit only after this new fiber exits.

  • parameter on

    the optional runner to use, added since 0.7

val spawn_top_ignore : on:Moonpool.Runner.t -> (unit -> _) -> unit

Like spawn_top but ignores the result.

  • since 0.7
include module type of struct include Main end
val main : (Moonpool.Runner.t -> 'a) -> 'a

main f runs f() in a scope that handles effects, including Fiber.await.

This scope can run background tasks as well, in a cooperative fashion.

val main' : ?block_signals:bool -> unit -> (Moonpool.Runner.t -> 'a) -> 'a

Same as main but with room for optional arguments.

  • since 0.7
diff --git a/moonpool/Moonpool_fib__Fiber/index.html b/moonpool/Moonpool_fib__Fiber/index.html deleted file mode 100644 index 5a8bcba6..00000000 --- a/moonpool/Moonpool_fib__Fiber/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Moonpool_fib__Fiber (moonpool.Moonpool_fib__Fiber)

Module Moonpool_fib__Fiber

This module is hidden.

diff --git a/moonpool/Moonpool_fib__Fls/index.html b/moonpool/Moonpool_fib__Fls/index.html deleted file mode 100644 index 61d2596a..00000000 --- a/moonpool/Moonpool_fib__Fls/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Moonpool_fib__Fls (moonpool.Moonpool_fib__Fls)

Module Moonpool_fib__Fls

This module is hidden.

diff --git a/moonpool/Moonpool_fib__Handle/index.html b/moonpool/Moonpool_fib__Handle/index.html deleted file mode 100644 index 464e5833..00000000 --- a/moonpool/Moonpool_fib__Handle/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Moonpool_fib__Handle (moonpool.Moonpool_fib__Handle)

Module Moonpool_fib__Handle

This module is hidden.

diff --git a/moonpool/Moonpool_fib__Main/index.html b/moonpool/Moonpool_fib__Main/index.html deleted file mode 100644 index 18f27b76..00000000 --- a/moonpool/Moonpool_fib__Main/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Moonpool_fib__Main (moonpool.Moonpool_fib__Main)

Module Moonpool_fib__Main

This module is hidden.

diff --git a/moonpool/_doc-dir/README.md b/moonpool/_doc-dir/README.md index 2c7e88de..810bea41 100644 --- a/moonpool/_doc-dir/README.md +++ b/moonpool/_doc-dir/README.md @@ -173,49 +173,9 @@ val expected_sum : int = 5050 We have a `Exn_bt.t` type that comes in handy in many places. It bundles together an exception and the backtrace associated with the place the exception was caught. -### Fibers +### Local storage -On OCaml 5, Moonpool comes with a library `moonpool.fib` (module `Moonpool_fib`) -which provides _lightweight fibers_ -that can run on any Moonpool runner. -These fibers are a sort of lightweight thread, dispatched on the runner's -background thread(s). -Fibers rely on effects to implement `Fiber.await`, suspending themselves until the `await`-ed fiber -is done. - -```ocaml -# #require "moonpool.fib";; -... - -# (* convenient alias *) - module F = Moonpool_fib;; -module F = Moonpool_fib -# F.main (fun _runner -> - let f1 = F.spawn (fun () -> fib 10) in - let f2 = F.spawn (fun () -> fib 15) in - F.await f1 + F.await f2);; -- : int = 1076 -``` - -Fibers form a _tree_, where a fiber calling `Fiber.spawn` to start a sub-fiber is -the sub-fiber's _parent_. -When a parent fails, all its children are cancelled (forced to fail). -This is a simple form of [Structured Concurrency](https://en.wikipedia.org/wiki/Structured_concurrency). - -Like a future, a fiber eventually _resolves_ into a value (or an `Exn_bt.t`) that it's possible -to `await`. With `Fiber.res : 'a Fiber.t -> 'a Fut.t` it's possible to access that result -as a regular future, too. -However, this resolution is only done after all the children of the fiber have -resolved — the lifetime of fibers forms a well-nested tree in that sense. - -When a fiber is suspended because it `await`s another fiber (or future), the scheduler's -thread on which it was running becomes available again and can go on process another task. -When the fiber resumes, it will automatically be re-scheduled on the same runner it started on. -This means fibers on pool P1 can await fibers from pool P2 and still be resumed on P1. - -In addition to all that, fibers provide _fiber local storage_ (like thread-local storage, but per fiber). -This storage is inherited in `spawn` (as a shallow copy only — it's advisable to only -put persistent data in storage to avoid confusing aliasing). +Moonpool, via picos, provides _task local storage_ (like thread-local storage, but per task). The storage is convenient for carrying around context for cross-cutting concerns such as logging or tracing (e.g. a log tag for the current user or request ID, or a tracing scope). diff --git a/moonpool/index.html b/moonpool/index.html index 06a93f0b..6ad06bb0 100644 --- a/moonpool/index.html +++ b/moonpool/index.html @@ -1,2 +1,2 @@ -index (moonpool.index)

Package moonpool

Package info

changes-files
readme-files
+index (moonpool.index)

Package moonpool

Package info

changes-files
readme-files