This commit is contained in:
c-cube 2024-03-05 01:52:16 +00:00
parent 846331d43c
commit c34156bfc1
24 changed files with 128 additions and 40 deletions

View file

@ -165,6 +165,57 @@ val expected_sum : int = 5050
- : unit = ()
```
### Errors
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
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).
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).
### Fork-join
On OCaml 5, again using effect handlers, the sublibrary `moonpool.forkjoin`

View file

@ -3,6 +3,6 @@
<span><span class="label">size</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> int)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">num_tasks</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> int)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">shutdown</span>:<span>(<span><span class="label">wait</span>:bool <span class="arrow">&#45;&gt;</span></span> <span>unit <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">run_async</span>:<span>(<span><span class="label">ls</span>:<a href="../../Task_local_storage/index.html#type-storage">Task_local_storage.storage</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="../index.html#type-task">task</a> <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">run_async</span>:<span>(<span><span class="label">ls</span>:<a href="../../Task_local_storage/index.html#type-t">Task_local_storage.t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="../index.html#type-task">task</a> <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span>unit <span class="arrow">&#45;&gt;</span></span>
<a href="../index.html#type-t">t</a></span></code></div><div class="spec-doc"><p>Create a new runner.</p><p><b>NOTE</b>: the runner should support DLA and <code>Suspend_</code> on OCaml 5.x, so that <code>Fork_join</code> and other 5.x features work properly.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-k_cur_runner"><a href="#val-k_cur_runner" class="anchor"></a><code><span><span class="keyword">val</span> k_cur_runner : <span><span><span><a href="../index.html#type-t">t</a> option</span> <a href="../../../../ocaml/Stdlib/index.html#type-ref">ref</a></span> <a href="../../../Moonpool_private/Thread_local_storage_/index.html#type-key">Moonpool_private.Thread_local_storage_.key</a></span></span></code></div><div class="spec-doc"><p>Key that should be used by each runner to store itself in TLS on every thread it controls, so that tasks running on these threads can access the runner. This is necessary for <a href="../index.html#val-get_current_runner"><code>get_current_runner</code></a> to work.</p></div></div></div></body></html>

File diff suppressed because one or more lines are too long

View file

@ -3,6 +3,6 @@
<span><span class="label">size</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> int)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">num_tasks</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> int)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">shutdown</span>:<span>(<span><span class="label">wait</span>:bool <span class="arrow">&#45;&gt;</span></span> <span>unit <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">run_async</span>:<span>(<span><span class="label">ls</span>:<a href="../../Task_local_storage/index.html#type-storage">Task_local_storage.storage</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="../index.html#type-task">task</a> <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">run_async</span>:<span>(<span><span class="label">ls</span>:<a href="../../Task_local_storage/index.html#type-t">Task_local_storage.t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="../index.html#type-task">task</a> <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span>unit <span class="arrow">&#45;&gt;</span></span>
<a href="../index.html#type-t">t</a></span></code></div><div class="spec-doc"><p>Create a new runner.</p><p><b>NOTE</b>: the runner should support DLA and <code>Suspend_</code> on OCaml 5.x, so that <code>Fork_join</code> and other 5.x features work properly.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-k_cur_runner"><a href="#val-k_cur_runner" class="anchor"></a><code><span><span class="keyword">val</span> k_cur_runner : <span><span><span><a href="../index.html#type-t">t</a> option</span> <a href="../../../../ocaml/Stdlib/index.html#type-ref">ref</a></span> <a href="../../../Moonpool_private/Thread_local_storage_/index.html#type-key">Moonpool_private.Thread_local_storage_.key</a></span></span></code></div><div class="spec-doc"><p>Key that should be used by each runner to store itself in TLS on every thread it controls, so that tasks running on these threads can access the runner. This is necessary for <a href="../index.html#val-get_current_runner"><code>get_current_runner</code></a> to work.</p></div></div></div></body></html>

File diff suppressed because one or more lines are too long

View file

@ -1,8 +0,0 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>For_runner_implementors (moonpool.Moonpool.Immediate_runner.For_runner_implementors)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../../../index.html">moonpool</a> &#x00BB; <a href="../../index.html">Moonpool</a> &#x00BB; <a href="../index.html">Immediate_runner</a> &#x00BB; For_runner_implementors</nav><header class="odoc-preamble"><h1>Module <code><span>Immediate_runner.For_runner_implementors</span></code></h1><p>This module is specifically intended for users who implement their own runners. Regular users of Moonpool should not need to look at it.</p></header><div class="odoc-content"><div class="odoc-spec"><div class="spec value anchored" id="val-create"><a href="#val-create" class="anchor"></a><code><span><span class="keyword">val</span> create :
<span><span class="label">size</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> int)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">num_tasks</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> int)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">shutdown</span>:<span>(<span><span class="label">wait</span>:bool <span class="arrow">&#45;&gt;</span></span> <span>unit <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">run_async</span>:<span>(<span><span class="label">ls</span>:<a href="../../Task_local_storage/index.html#type-storage">Task_local_storage.storage</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="../index.html#type-task">task</a> <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span>unit <span class="arrow">&#45;&gt;</span></span>
<a href="../index.html#type-t">t</a></span></code></div><div class="spec-doc"><p>Create a new runner.</p><p><b>NOTE</b>: the runner should support DLA and <code>Suspend_</code> on OCaml 5.x, so that <code>Fork_join</code> and other 5.x features work properly.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-k_cur_runner"><a href="#val-k_cur_runner" class="anchor"></a><code><span><span class="keyword">val</span> k_cur_runner : <span><span><span><a href="../index.html#type-t">t</a> option</span> <a href="../../../../ocaml/Stdlib/index.html#type-ref">ref</a></span> <a href="../../../Moonpool_private/Thread_local_storage_/index.html#type-key">Moonpool_private.Thread_local_storage_.key</a></span></span></code></div><div class="spec-doc"><p>Key that should be used by each runner to store itself in TLS on every thread it controls, so that tasks running on these threads can access the runner. This is necessary for <a href="../index.html#val-get_current_runner"><code>get_current_runner</code></a> to work.</p></div></div></div></body></html>

File diff suppressed because one or more lines are too long

View file

@ -3,6 +3,6 @@
<span><span class="label">size</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> int)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">num_tasks</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> int)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">shutdown</span>:<span>(<span><span class="label">wait</span>:bool <span class="arrow">&#45;&gt;</span></span> <span>unit <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">run_async</span>:<span>(<span><span class="label">ls</span>:<a href="../../Task_local_storage/index.html#type-storage">Task_local_storage.storage</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="../index.html#type-task">task</a> <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">run_async</span>:<span>(<span><span class="label">ls</span>:<a href="../../Task_local_storage/index.html#type-t">Task_local_storage.t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="../index.html#type-task">task</a> <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span>unit <span class="arrow">&#45;&gt;</span></span>
<a href="../index.html#type-t">t</a></span></code></div><div class="spec-doc"><p>Create a new runner.</p><p><b>NOTE</b>: the runner should support DLA and <code>Suspend_</code> on OCaml 5.x, so that <code>Fork_join</code> and other 5.x features work properly.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-k_cur_runner"><a href="#val-k_cur_runner" class="anchor"></a><code><span><span class="keyword">val</span> k_cur_runner : <span><span><span><a href="../index.html#type-t">t</a> option</span> <a href="../../../../ocaml/Stdlib/index.html#type-ref">ref</a></span> <a href="../../../Moonpool_private/Thread_local_storage_/index.html#type-key">Moonpool_private.Thread_local_storage_.key</a></span></span></code></div><div class="spec-doc"><p>Key that should be used by each runner to store itself in TLS on every thread it controls, so that tasks running on these threads can access the runner. This is necessary for <a href="../index.html#val-get_current_runner"><code>get_current_runner</code></a> to work.</p></div></div></div></body></html>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,2 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Direct (moonpool.Moonpool.Task_local_storage.Direct)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../../../index.html">moonpool</a> &#x00BB; <a href="../../index.html">Moonpool</a> &#x00BB; <a href="../index.html">Task_local_storage</a> &#x00BB; Direct</nav><header class="odoc-preamble"><h1>Module <code><span>Task_local_storage.Direct</span></code></h1><p>Direct access to values from a storage handle</p></header><div class="odoc-content"><div class="odoc-spec"><div class="spec value anchored" id="val-get"><a href="#val-get" class="anchor"></a><code><span><span class="keyword">val</span> get : <span><a href="../index.html#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><span><span class="type-var">'a</span> <a href="../index.html#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'a</span></span></code></div><div class="spec-doc"><p>Access a key</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-set"><a href="#val-set" class="anchor"></a><code><span><span class="keyword">val</span> set : <span><a href="../index.html#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><span><span class="type-var">'a</span> <a href="../index.html#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span> unit</span></code></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-create"><a href="#val-create" class="anchor"></a><code><span><span class="keyword">val</span> create : <span>unit <span class="arrow">&#45;&gt;</span></span> <a href="../index.html#type-t">t</a></span></code></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-copy"><a href="#val-copy" class="anchor"></a><code><span><span class="keyword">val</span> copy : <span><a href="../index.html#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <a href="../index.html#type-t">t</a></span></code></div></div></div></body></html>

View file

@ -1,8 +1,8 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Task_local_storage (moonpool.Moonpool.Task_local_storage)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../../index.html">moonpool</a> &#x00BB; <a href="../index.html">Moonpool</a> &#x00BB; Task_local_storage</nav><header class="odoc-preamble"><h1>Module <code><span>Moonpool.Task_local_storage</span></code></h1><p>Task-local storage.</p><p>This storage is associated to the current task, just like thread-local storage is associated with the current thread. The storage is carried along in case the current task is suspended.</p><ul class="at-tags"><li class="since"><span class="at-tag">since</span> NEXT_RELEASE</li></ul></header><div class="odoc-content"><div class="odoc-spec"><div class="spec type anchored" id="type-storage"><a href="#type-storage" class="anchor"></a><code><span><span class="keyword">type</span> storage</span></code></div><div class="spec-doc"><p>Underlying storage for a task</p></div></div><div class="odoc-spec"><div class="spec type anchored" id="type-key"><a href="#type-key" class="anchor"></a><code><span><span class="keyword">type</span> <span>'a key</span></span></code></div><div class="spec-doc"><p>A key used to access a particular (typed) storage slot on every task.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-new_key"><a href="#val-new_key" class="anchor"></a><code><span><span class="keyword">val</span> new_key : <span><span class="label">init</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'a</span>)</span> <span class="arrow">&#45;&gt;</span></span> <span>unit <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <a href="#type-key">key</a></span></span></code></div><div class="spec-doc"><p><code>new_key ~init ()</code> makes a new key. Keys are expensive and should never be allocated dynamically or in a loop. The correct pattern is, at toplevel:</p><pre class="language-ocaml"><code> let k_foo : foo Task_ocal_storage.key =
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Task_local_storage (moonpool.Moonpool.Task_local_storage)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../../index.html">moonpool</a> &#x00BB; <a href="../index.html">Moonpool</a> &#x00BB; Task_local_storage</nav><header class="odoc-preamble"><h1>Module <code><span>Moonpool.Task_local_storage</span></code></h1><p>Task-local storage.</p><p>This storage is associated to the current task, just like thread-local storage is associated with the current thread. The storage is carried along in case the current task is suspended.</p><ul class="at-tags"><li class="since"><span class="at-tag">since</span> NEXT_RELEASE</li></ul></header><div class="odoc-content"><div class="odoc-spec"><div class="spec type anchored" id="type-t"><a href="#type-t" class="anchor"></a><code><span><span class="keyword">type</span> t</span><span> = <span class="xref-unresolved">Moonpool__</span>.Types_.local_storage</span></code></div><div class="spec-doc"><p>Underlying storage for a task. This is mutable and not thread-safe.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-dummy"><a href="#val-dummy" class="anchor"></a><code><span><span class="keyword">val</span> dummy : <a href="#type-t">t</a></span></code></div></div><div class="odoc-spec"><div class="spec type anchored" id="type-key"><a href="#type-key" class="anchor"></a><code><span><span class="keyword">type</span> <span>'a key</span></span></code></div><div class="spec-doc"><p>A key used to access a particular (typed) storage slot on every task.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-new_key"><a href="#val-new_key" class="anchor"></a><code><span><span class="keyword">val</span> new_key : <span><span class="label">init</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'a</span>)</span> <span class="arrow">&#45;&gt;</span></span> <span>unit <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <a href="#type-key">key</a></span></span></code></div><div class="spec-doc"><p><code>new_key ~init ()</code> makes a new key. Keys are expensive and should never be allocated dynamically or in a loop. The correct pattern is, at toplevel:</p><pre class="language-ocaml"><code> let k_foo : foo Task_ocal_storage.key =
Task_local_storage.new_key ~init:(fun () -&gt; make_foo ()) ()
(* … *)
(* use it: *)
let … = Task_local_storage.get k_foo</code></pre></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-get"><a href="#val-get" class="anchor"></a><code><span><span class="keyword">val</span> get : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'a</span></span></code></div><div class="spec-doc"><p><code>get k</code> gets the value for the current task for key <code>k</code>. Must be run from inside a task running on a runner.</p><ul class="at-tags"><li class="raises"><span class="at-tag">raises</span> <code>Failure</code> <p>otherwise</p></li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-get_opt"><a href="#val-get_opt" class="anchor"></a><code><span><span class="keyword">val</span> get_opt : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> option</span></span></code></div><div class="spec-doc"><p><code>get_opt k</code> gets the current task's value for key <code>k</code>, or <code>None</code> if not run from inside the task.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-set"><a href="#val-set" class="anchor"></a><code><span><span class="keyword">val</span> set : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span> unit</span></code></div><div class="spec-doc"><p><code>set k v</code> sets the storage for <code>k</code> to <code>v</code>. Must be run from inside a task running on a runner.</p><ul class="at-tags"><li class="raises"><span class="at-tag">raises</span> <code>Failure</code> <p>otherwise</p></li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-with_value"><a href="#val-with_value" class="anchor"></a><code><span><span class="keyword">val</span> with_value : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span> <span><span>(<span>unit <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'b</span>)</span> <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'b</span></span></code></div><div class="spec-doc"><p><code>with_value k v f</code> sets <code>k</code> to <code>v</code> for the duration of the call to <code>f()</code>. When <code>f()</code> returns (or fails), <code>k</code> is restored to its old value.</p></div></div></div></body></html>
let … = Task_local_storage.get k_foo</code></pre></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-get"><a href="#val-get" class="anchor"></a><code><span><span class="keyword">val</span> get : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'a</span></span></code></div><div class="spec-doc"><p><code>get k</code> gets the value for the current task for key <code>k</code>. Must be run from inside a task running on a runner.</p><ul class="at-tags"><li class="raises"><span class="at-tag">raises</span> <code>Failure</code> <p>otherwise</p></li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-get_opt"><a href="#val-get_opt" class="anchor"></a><code><span><span class="keyword">val</span> get_opt : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> option</span></span></code></div><div class="spec-doc"><p><code>get_opt k</code> gets the current task's value for key <code>k</code>, or <code>None</code> if not run from inside the task.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-set"><a href="#val-set" class="anchor"></a><code><span><span class="keyword">val</span> set : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span> unit</span></code></div><div class="spec-doc"><p><code>set k v</code> sets the storage for <code>k</code> to <code>v</code>. Must be run from inside a task running on a runner.</p><ul class="at-tags"><li class="raises"><span class="at-tag">raises</span> <code>Failure</code> <p>otherwise</p></li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-with_value"><a href="#val-with_value" class="anchor"></a><code><span><span class="keyword">val</span> with_value : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span> <span><span>(<span>unit <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'b</span>)</span> <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'b</span></span></code></div><div class="spec-doc"><p><code>with_value k v f</code> sets <code>k</code> to <code>v</code> for the duration of the call to <code>f()</code>. When <code>f()</code> returns (or fails), <code>k</code> is restored to its old value.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-get_current"><a href="#val-get_current" class="anchor"></a><code><span><span class="keyword">val</span> get_current : <span>unit <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> option</span></span></code></div><div class="spec-doc"><p>Access the current storage, or <code>None</code> if not run from within a task.</p></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Direct"><a href="#module-Direct" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Direct/index.html">Direct</a></span><span> : <span class="keyword">sig</span> ... <span class="keyword">end</span></span></code></div><div class="spec-doc"><p>Direct access to values from a storage handle</p></div></div></div></body></html>

View file

@ -3,6 +3,6 @@
<span><span class="label">size</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> int)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">num_tasks</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> int)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">shutdown</span>:<span>(<span><span class="label">wait</span>:bool <span class="arrow">&#45;&gt;</span></span> <span>unit <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">run_async</span>:<span>(<span><span class="label">ls</span>:<a href="../../Task_local_storage/index.html#type-storage">Task_local_storage.storage</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="../index.html#type-task">task</a> <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span><span class="label">run_async</span>:<span>(<span><span class="label">ls</span>:<a href="../../Task_local_storage/index.html#type-t">Task_local_storage.t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="../index.html#type-task">task</a> <span class="arrow">&#45;&gt;</span></span> unit)</span> <span class="arrow">&#45;&gt;</span></span>
<span>unit <span class="arrow">&#45;&gt;</span></span>
<a href="../index.html#type-t">t</a></span></code></div><div class="spec-doc"><p>Create a new runner.</p><p><b>NOTE</b>: the runner should support DLA and <code>Suspend_</code> on OCaml 5.x, so that <code>Fork_join</code> and other 5.x features work properly.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-k_cur_runner"><a href="#val-k_cur_runner" class="anchor"></a><code><span><span class="keyword">val</span> k_cur_runner : <span><span><span><a href="../index.html#type-t">t</a> option</span> <a href="../../../../ocaml/Stdlib/index.html#type-ref">ref</a></span> <a href="../../../Moonpool_private/Thread_local_storage_/index.html#type-key">Moonpool_private.Thread_local_storage_.key</a></span></span></code></div><div class="spec-doc"><p>Key that should be used by each runner to store itself in TLS on every thread it controls, so that tasks running on these threads can access the runner. This is necessary for <a href="../index.html#val-get_current_runner"><code>get_current_runner</code></a> to work.</p></div></div></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,2 +0,0 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Moonpool__Immediate_runner (moonpool.Moonpool__Immediate_runner)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../index.html">moonpool</a> &#x00BB; Moonpool__Immediate_runner</nav><header class="odoc-preamble"><h1>Module <code><span>Moonpool__Immediate_runner</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>

File diff suppressed because one or more lines are too long

View file

@ -1,8 +1,8 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Fls (moonpool.Moonpool_fib.Fls)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../../index.html">moonpool</a> &#x00BB; <a href="../index.html">Moonpool_fib</a> &#x00BB; Fls</nav><header class="odoc-preamble"><h1>Module <code><span>Moonpool_fib.Fls</span></code></h1><p>Fiber-local storage.</p><p>This storage is associated to the current fiber, just like thread-local storage is associated with the current thread.</p><p>See <a href="../../Moonpool/Task_local_storage/index.html"><code>Moonpool.Task_local_storage</code></a> for more general information, as this is based on it.</p><p><b>NOTE</b>: it's important to note that, while each fiber has its own storage, spawning a sub-fiber <code>f2</code> from a fiber <code>f1</code> will only do a shallow copy of the storage. Values inside <code>f1</code>'s storage will be physically shared with <code>f2</code>.</p></header><div class="odoc-content"><div class="odoc-include"><details open="open"><summary class="spec include"><code><span><span class="keyword">include</span> <span class="keyword">module</span> <span class="keyword">type</span> <span class="keyword">of</span> <span class="keyword">struct</span> <span class="keyword">include</span> <a href="../../Moonpool/Task_local_storage/index.html">Moonpool.Task_local_storage</a> <span class="keyword">end</span></span></code></summary><div class="odoc-spec"><div class="spec type anchored" id="type-storage"><a href="#type-storage" class="anchor"></a><code><span><span class="keyword">type</span> storage</span><span> = <a href="../../Moonpool/Task_local_storage/index.html#type-storage">Moonpool.Task_local_storage.storage</a></span></code></div><div class="spec-doc"><p>Underlying storage for a task</p></div></div><div class="odoc-spec"><div class="spec type anchored" id="type-key"><a href="#type-key" class="anchor"></a><code><span><span class="keyword">type</span> <span>'a key</span></span><span> = <span><span class="type-var">'a</span> <a href="../../Moonpool/Task_local_storage/index.html#type-key">Moonpool.Task_local_storage.key</a></span></span></code></div><div class="spec-doc"><p>A key used to access a particular (typed) storage slot on every task.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-new_key"><a href="#val-new_key" class="anchor"></a><code><span><span class="keyword">val</span> new_key : <span><span class="label">init</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'a</span>)</span> <span class="arrow">&#45;&gt;</span></span> <span>unit <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <a href="#type-key">key</a></span></span></code></div><div class="spec-doc"><p><code>new_key ~init ()</code> makes a new key. Keys are expensive and should never be allocated dynamically or in a loop. The correct pattern is, at toplevel:</p><pre class="language-ocaml"><code> let k_foo : foo Task_ocal_storage.key =
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Fls (moonpool.Moonpool_fib.Fls)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../../index.html">moonpool</a> &#x00BB; <a href="../index.html">Moonpool_fib</a> &#x00BB; Fls</nav><header class="odoc-preamble"><h1>Module <code><span>Moonpool_fib.Fls</span></code></h1><p>Fiber-local storage.</p><p>This storage is associated to the current fiber, just like thread-local storage is associated with the current thread.</p><p>See <a href="../../Moonpool/Task_local_storage/index.html"><code>Moonpool.Task_local_storage</code></a> for more general information, as this is based on it.</p><p><b>NOTE</b>: it's important to note that, while each fiber has its own storage, spawning a sub-fiber <code>f2</code> from a fiber <code>f1</code> will only do a shallow copy of the storage. Values inside <code>f1</code>'s storage will be physically shared with <code>f2</code>. It is thus recommended to store only persistent values in the local storage.</p></header><div class="odoc-content"><div class="odoc-include"><details open="open"><summary class="spec include"><code><span><span class="keyword">include</span> <span class="keyword">module</span> <span class="keyword">type</span> <span class="keyword">of</span> <span class="keyword">struct</span> <span class="keyword">include</span> <a href="../../Moonpool/Task_local_storage/index.html">Moonpool.Task_local_storage</a> <span class="keyword">end</span></span></code></summary><div class="odoc-spec"><div class="spec type anchored" id="type-t"><a href="#type-t" class="anchor"></a><code><span><span class="keyword">type</span> t</span><span> = <span class="xref-unresolved">Moonpool__</span>.Types_.local_storage</span></code></div><div class="spec-doc"><p>Underlying storage for a task. This is mutable and not thread-safe.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-dummy"><a href="#val-dummy" class="anchor"></a><code><span><span class="keyword">val</span> dummy : <a href="#type-t">t</a></span></code></div></div><div class="odoc-spec"><div class="spec type anchored" id="type-key"><a href="#type-key" class="anchor"></a><code><span><span class="keyword">type</span> <span>'a key</span></span><span> = <span><span class="type-var">'a</span> <a href="../../Moonpool/Task_local_storage/index.html#type-key">Moonpool.Task_local_storage.key</a></span></span></code></div><div class="spec-doc"><p>A key used to access a particular (typed) storage slot on every task.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-new_key"><a href="#val-new_key" class="anchor"></a><code><span><span class="keyword">val</span> new_key : <span><span class="label">init</span>:<span>(<span>unit <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'a</span>)</span> <span class="arrow">&#45;&gt;</span></span> <span>unit <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <a href="#type-key">key</a></span></span></code></div><div class="spec-doc"><p><code>new_key ~init ()</code> makes a new key. Keys are expensive and should never be allocated dynamically or in a loop. The correct pattern is, at toplevel:</p><pre class="language-ocaml"><code> let k_foo : foo Task_ocal_storage.key =
Task_local_storage.new_key ~init:(fun () -&gt; make_foo ()) ()
(* … *)
(* use it: *)
let … = Task_local_storage.get k_foo</code></pre></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-get"><a href="#val-get" class="anchor"></a><code><span><span class="keyword">val</span> get : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'a</span></span></code></div><div class="spec-doc"><p><code>get k</code> gets the value for the current task for key <code>k</code>. Must be run from inside a task running on a runner.</p><ul class="at-tags"><li class="raises"><span class="at-tag">raises</span> <code>Failure</code> <p>otherwise</p></li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-get_opt"><a href="#val-get_opt" class="anchor"></a><code><span><span class="keyword">val</span> get_opt : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> option</span></span></code></div><div class="spec-doc"><p><code>get_opt k</code> gets the current task's value for key <code>k</code>, or <code>None</code> if not run from inside the task.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-set"><a href="#val-set" class="anchor"></a><code><span><span class="keyword">val</span> set : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span> unit</span></code></div><div class="spec-doc"><p><code>set k v</code> sets the storage for <code>k</code> to <code>v</code>. Must be run from inside a task running on a runner.</p><ul class="at-tags"><li class="raises"><span class="at-tag">raises</span> <code>Failure</code> <p>otherwise</p></li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-with_value"><a href="#val-with_value" class="anchor"></a><code><span><span class="keyword">val</span> with_value : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span> <span><span>(<span>unit <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'b</span>)</span> <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'b</span></span></code></div><div class="spec-doc"><p><code>with_value k v f</code> sets <code>k</code> to <code>v</code> for the duration of the call to <code>f()</code>. When <code>f()</code> returns (or fails), <code>k</code> is restored to its old value.</p></div></div></details></div></div></body></html>
let … = Task_local_storage.get k_foo</code></pre></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-get"><a href="#val-get" class="anchor"></a><code><span><span class="keyword">val</span> get : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'a</span></span></code></div><div class="spec-doc"><p><code>get k</code> gets the value for the current task for key <code>k</code>. Must be run from inside a task running on a runner.</p><ul class="at-tags"><li class="raises"><span class="at-tag">raises</span> <code>Failure</code> <p>otherwise</p></li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-get_opt"><a href="#val-get_opt" class="anchor"></a><code><span><span class="keyword">val</span> get_opt : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> option</span></span></code></div><div class="spec-doc"><p><code>get_opt k</code> gets the current task's value for key <code>k</code>, or <code>None</code> if not run from inside the task.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-set"><a href="#val-set" class="anchor"></a><code><span><span class="keyword">val</span> set : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span> unit</span></code></div><div class="spec-doc"><p><code>set k v</code> sets the storage for <code>k</code> to <code>v</code>. Must be run from inside a task running on a runner.</p><ul class="at-tags"><li class="raises"><span class="at-tag">raises</span> <code>Failure</code> <p>otherwise</p></li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-with_value"><a href="#val-with_value" class="anchor"></a><code><span><span class="keyword">val</span> with_value : <span><span><span class="type-var">'a</span> <a href="#type-key">key</a></span> <span class="arrow">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span> <span><span>(<span>unit <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'b</span>)</span> <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'b</span></span></code></div><div class="spec-doc"><p><code>with_value k v f</code> sets <code>k</code> to <code>v</code> for the duration of the call to <code>f()</code>. When <code>f()</code> returns (or fails), <code>k</code> is restored to its old value.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-get_current"><a href="#val-get_current" class="anchor"></a><code><span><span class="keyword">val</span> get_current : <span>unit <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> option</span></span></code></div><div class="spec-doc"><p>Access the current storage, or <code>None</code> if not run from within a task.</p></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Direct"><a href="#module-Direct" class="anchor"></a><code><span><span class="keyword">module</span> Direct</span><span> = <a href="../../Moonpool/Task_local_storage/Direct/index.html">Moonpool.Task_local_storage.Direct</a></span></code></div><div class="spec-doc"><p>Direct access to values from a storage handle</p></div></div></details></div></div></body></html>

View file

@ -1,2 +1,2 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Handle (moonpool.Moonpool_fib.Handle)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../../index.html">moonpool</a> &#x00BB; <a href="../index.html">Moonpool_fib</a> &#x00BB; Handle</nav><header class="odoc-preamble"><h1>Module <code><span>Moonpool_fib.Handle</span></code></h1><p>The unique name of a fiber</p></header><div class="odoc-content"><div class="odoc-spec"><div class="spec type anchored" id="type-t"><a href="#type-t" class="anchor"></a><code><span><span class="keyword">type</span> t</span><span> = <span class="keyword">private</span> int</span></code></div><div class="spec-doc"><p>Unique, opaque identifier for a fiber.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-equal"><a href="#val-equal" class="anchor"></a><code><span><span class="keyword">val</span> equal : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> bool</span></code></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-compare"><a href="#val-compare" class="anchor"></a><code><span><span class="keyword">val</span> compare : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> int</span></code></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-hash"><a href="#val-hash" class="anchor"></a><code><span><span class="keyword">val</span> hash : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> int</span></code></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-generate_fresh"><a href="#val-generate_fresh" class="anchor"></a><code><span><span class="keyword">val</span> generate_fresh : <span>unit <span class="arrow">&#45;&gt;</span></span> <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p>Generate a fresh, unique identifier</p></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Set"><a href="#module-Set" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Set/index.html">Set</a></span><span> : <a href="../../../ocaml/Stdlib/Set/module-type-S/index.html">Set.S</a> <span class="keyword">with</span> <span><span class="keyword">type</span> <a href="../../../ocaml/Stdlib/Set/module-type-S/index.html#type-elt">elt</a> = <a href="#type-t">t</a></span></span></code></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Map"><a href="#module-Map" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Map/index.html">Map</a></span><span> : <a href="../../../ocaml/Stdlib/Map/module-type-S/index.html">Map.S</a> <span class="keyword">with</span> <span><span class="keyword">type</span> <a href="../../../ocaml/Stdlib/Map/module-type-S/index.html#type-key">key</a> = <a href="#type-t">t</a></span></span></code></div></div></div></body></html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Handle (moonpool.Moonpool_fib.Handle)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../../index.html">moonpool</a> &#x00BB; <a href="../index.html">Moonpool_fib</a> &#x00BB; Handle</nav><header class="odoc-preamble"><h1>Module <code><span>Moonpool_fib.Handle</span></code></h1><p>The unique name of a fiber.</p><p>Each fiber has a unique handle that can be used to refer to it in maps or sets.</p></header><div class="odoc-content"><div class="odoc-spec"><div class="spec type anchored" id="type-t"><a href="#type-t" class="anchor"></a><code><span><span class="keyword">type</span> t</span><span> = <span class="keyword">private</span> int</span></code></div><div class="spec-doc"><p>Unique, opaque identifier for a fiber.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-equal"><a href="#val-equal" class="anchor"></a><code><span><span class="keyword">val</span> equal : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> bool</span></code></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-compare"><a href="#val-compare" class="anchor"></a><code><span><span class="keyword">val</span> compare : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> int</span></code></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-hash"><a href="#val-hash" class="anchor"></a><code><span><span class="keyword">val</span> hash : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> int</span></code></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-generate_fresh"><a href="#val-generate_fresh" class="anchor"></a><code><span><span class="keyword">val</span> generate_fresh : <span>unit <span class="arrow">&#45;&gt;</span></span> <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p>Generate a fresh, unique identifier</p></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Set"><a href="#module-Set" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Set/index.html">Set</a></span><span> : <a href="../../../ocaml/Stdlib/Set/module-type-S/index.html">Set.S</a> <span class="keyword">with</span> <span><span class="keyword">type</span> <a href="../../../ocaml/Stdlib/Set/module-type-S/index.html#type-elt">elt</a> = <a href="#type-t">t</a></span></span></code></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Map"><a href="#module-Map" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Map/index.html">Map</a></span><span> : <a href="../../../ocaml/Stdlib/Map/module-type-S/index.html">Map.S</a> <span class="keyword">with</span> <span><span class="keyword">type</span> <a href="../../../ocaml/Stdlib/Map/module-type-S/index.html#type-key">key</a> = <a href="#type-t">t</a></span></span></code></div></div></div></body></html>

View file

@ -0,0 +1,2 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Main (moonpool.Moonpool_fib.Main)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../../index.html">moonpool</a> &#x00BB; <a href="../index.html">Moonpool_fib</a> &#x00BB; Main</nav><header class="odoc-preamble"><h1>Module <code><span>Moonpool_fib.Main</span></code></h1><p>Main thread.</p><p>This is evolved from <code>Moonpool.Immediate_runner</code>, 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.</p><p>This means it's reasonable to use <code>Main.main (fun () -&gt; do_everything)</code> 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 <code>Fiber.await</code>.</p><p>Aside from the fact that this blocks the caller thread, it is fairly similar to <code>Background_thread</code> in that there's a single worker to process tasks/fibers.</p><p>This handles effects, including the ones in <a href="../Fiber/index.html"><code>Fiber</code></a>.</p><ul class="at-tags"><li class="since"><span class="at-tag">since</span> NEXT_RELEASE</li></ul></header><div class="odoc-content"><div class="odoc-spec"><div class="spec value anchored" id="val-main"><a href="#val-main" class="anchor"></a><code><span><span class="keyword">val</span> main : <span><span>(<span><a href="../../Moonpool/Runner/index.html#type-t">Moonpool.Runner.t</a> <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'a</span>)</span> <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'a</span></span></code></div><div class="spec-doc"><p><code>main f</code> runs <code>f()</code> in a scope that handles effects, including <a href="../Fiber/index.html#val-await"><code>Fiber.await</code></a>.</p><p>This scope can run background tasks as well, in a cooperative fashion.</p></div></div></div></body></html>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,2 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Moonpool_fib__ (moonpool.Moonpool_fib__)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../index.html">moonpool</a> &#x00BB; Moonpool_fib__</nav><header class="odoc-preamble"><h1>Module <code><span>Moonpool_fib__</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>

View file

@ -0,0 +1,2 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Moonpool_fib__Main (moonpool.Moonpool_fib__Main)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../index.html">moonpool</a> &#x00BB; Moonpool_fib__Main</nav><header class="odoc-preamble"><h1>Module <code><span>Moonpool_fib__Main</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>

View file

@ -165,6 +165,57 @@ val expected_sum : int = 5050
- : unit = ()
```
### Errors
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
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).
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).
### Fork-join
On OCaml 5, again using effect handlers, the sublibrary `moonpool.forkjoin`

View file

@ -1,2 +1,2 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>index (moonpool.index)</title><meta charset="utf-8"/><link rel="stylesheet" href="../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> moonpool</nav><header class="odoc-preamble"><h1 id="package-moonpool"><a href="#package-moonpool" class="anchor"></a>Package moonpool <nav><a type="text/plain; charset=UTF-8" href="_doc-dir/CHANGES.md">changes</a> <a href="#package_info">more…</a></nav></h1><ul class="modules"><li><a href="Moonpool/index.html"><code>Moonpool</code></a> <span class="synopsis">Moonpool</span></li><li><a href="Moonpool_fib/index.html"><code>Moonpool_fib</code></a> </li><li><a href="Moonpool_forkjoin/index.html"><code>Moonpool_forkjoin</code></a> <span class="synopsis">Fork-join primitives.</span></li><li><a href="Moonpool_private/index.html"><code>Moonpool_private</code></a> </li></ul></header><nav class="odoc-toc"><ul><li><a href="#package_info">Package info</a></li></ul></nav><div class="odoc-content"><h2 id="package_info"><a href="#package_info" class="anchor"></a>Package info</h2><table class="package info"><tr id="info-changes-files"><td><a href="#info-changes-files" aria-hidden="true" class="anchor"></a>changes-files</td><td><ul><li><a type="text/plain; charset=UTF-8" href="_doc-dir/CHANGES.md">CHANGES.md</a></li></ul></td></tr><tr id="info-readme-files"><td><a href="#info-readme-files" aria-hidden="true" class="anchor"></a>readme-files</td><td><ul><li><a type="text/plain; charset=UTF-8" href="_doc-dir/README.md">README.md</a></li></ul></td></tr></table></div></body></html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>index (moonpool.index)</title><meta charset="utf-8"/><link rel="stylesheet" href="../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.1"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> moonpool</nav><header class="odoc-preamble"><h1 id="package-moonpool"><a href="#package-moonpool" class="anchor"></a>Package moonpool <nav><a type="text/plain; charset=UTF-8" href="_doc-dir/CHANGES.md">changes</a> <a href="#package_info">more…</a></nav></h1><ul class="modules"><li><a href="Moonpool/index.html"><code>Moonpool</code></a> <span class="synopsis">Moonpool</span></li><li><a href="Moonpool_fib/index.html"><code>Moonpool_fib</code></a> <span class="synopsis">Fiber for moonpool</span></li><li><a href="Moonpool_forkjoin/index.html"><code>Moonpool_forkjoin</code></a> <span class="synopsis">Fork-join primitives.</span></li><li><a href="Moonpool_private/index.html"><code>Moonpool_private</code></a> </li></ul></header><nav class="odoc-toc"><ul><li><a href="#package_info">Package info</a></li></ul></nav><div class="odoc-content"><h2 id="package_info"><a href="#package_info" class="anchor"></a>Package info</h2><table class="package info"><tr id="info-changes-files"><td><a href="#info-changes-files" aria-hidden="true" class="anchor"></a>changes-files</td><td><ul><li><a type="text/plain; charset=UTF-8" href="_doc-dir/CHANGES.md">CHANGES.md</a></li></ul></td></tr><tr id="info-readme-files"><td><a href="#info-readme-files" aria-hidden="true" class="anchor"></a>readme-files</td><td><ul><li><a type="text/plain; charset=UTF-8" href="_doc-dir/README.md">README.md</a></li></ul></td></tr></table></div></body></html>