mirror of
https://github.com/c-cube/nanoev.git
synced 2025-12-06 03:05:32 -05:00
42 lines
31 KiB
HTML
42 lines
31 KiB
HTML
<!DOCTYPE html>
|
||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Fiber (picos.Picos.Fiber)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.0.0"/><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">Index</a> » <a href="../../index.html">picos</a> » <a href="../index.html">Picos</a> » Fiber</nav><header class="odoc-preamble"><h1>Module <code><span>Picos.Fiber</span></code></h1><p>An independent thread of execution.</p><p>A fiber corresponds to an independent thread of execution. Fibers are <a href="#val-create"><code>create</code></a>d by schedulers in response to <a href="#extension-Spawn"><code>Spawn</code></a> effects. A fiber is associated with a <a href="../Computation/index.html" title="Computation">computation</a> and either <a href="#val-forbid"><code>forbid</code></a>s or <a href="#val-permit"><code>permit</code></a>s the scheduler from propagating cancelation when the fiber performs effects. A fiber also has an associated <a href="FLS/index.html" title="FLS">fiber local storage</a>.</p><p>⚠️ Many operations on fibers can only be called safely from the fiber itself, because those operations are neither concurrency nor parallelism safe. Such operations can be safely called from a handler in a scheduler when it is handling an effect performed by the fiber. In particular, a scheduler can safely check whether the fiber <a href="#val-has_forbidden"><code>has_forbidden</code></a> cancelation and may access the <a href="FLS/index.html"><code>FLS</code></a> of the fiber.</p></header><div class="odoc-tocs"><nav class="odoc-toc odoc-local-toc"><ul><li><a href="#interface-for-rescheduling">Interface for rescheduling</a></li><li><a href="#interface-for-current-fiber">Interface for current fiber</a></li><li><a href="#interface-for-spawning">Interface for spawning</a></li><li><a href="#interface-for-structuring">Interface for structuring</a></li><li><a href="#interface-for-foreign-fiber">Interface for foreign fiber</a></li><li><a href="#interface-for-schedulers">Interface for schedulers</a></li><li><a href="#design-rationale">Design rationale</a></li></ul></nav></div><div class="odoc-content"><h3 id="interface-for-rescheduling"><a href="#interface-for-rescheduling" class="anchor"></a>Interface for rescheduling</h3><div class="odoc-spec"><div class="spec value anchored" id="val-yield"><a href="#val-yield" class="anchor"></a><code><span><span class="keyword">val</span> yield : <span>unit <span class="arrow">-></span></span> unit</span></code></div><div class="spec-doc"><p><code>yield ()</code> asks the current fiber to be rescheduled.</p><p>ℹ️ The behavior is that</p><ul><li>on OCaml 5, <code>yield</code> perform the <a href="#extension-Yield"><code>Yield</code></a> effect, and</li><li>on OCaml 4, <code>yield</code> will call the <code>yield</code> operation of the <a href="../Handler/index.html" title="Handler">current handler</a>.</li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-sleep"><a href="#val-sleep" class="anchor"></a><code><span><span class="keyword">val</span> sleep : <span><span class="label">seconds</span>:float <span class="arrow">-></span></span> unit</span></code></div><div class="spec-doc"><p><code>sleep ~seconds</code> suspends the current fiber for the specified number of <code>seconds</code>.</p></div></div><h3 id="interface-for-current-fiber"><a href="#interface-for-current-fiber" class="anchor"></a>Interface for current fiber</h3><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></code></div><div class="spec-doc"><p>Represents a fiber or an independent thread of execution.</p><p>⚠️ Unlike with most other concepts of Picos, operations on fibers are typically <i>not</i> concurrency or parallelism safe, because the fiber is considered to be owned by a single thread of execution.</p></div></div><div class="odoc-spec"><div class="spec type subst anchored" id="type-fiber"><a href="#type-fiber" class="anchor"></a><code><span><span class="keyword">type</span> fiber</span><span> := <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p>Type alias for <a href="#type-t"><code>Fiber.t</code></a> within this signature.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-current"><a href="#val-current" class="anchor"></a><code><span><span class="keyword">val</span> current : <span>unit <span class="arrow">-></span></span> <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p><code>current ()</code> returns the current fiber.</p><p>⚠️ Extra care should be taken when storing the fiber object in any shared data structure, because, aside from checking whether two fibers are <a href="#val-equal"><code>equal</code></a>, it is generally unsafe to perform any operations on foreign fibers.</p><p>ℹ️ The behavior is that</p><ul><li>on OCaml 5, <code>current</code> performs the <a href="#extension-Current"><code>Current</code></a> effect, and</li><li>on OCaml 4, <code>current</code> will call the <code>current</code> operation of the <a href="../Handler/index.html" title="Handler">current handler</a>.</li></ul><p>⚠️ The <code>current</code> operation must always resume the fiber without propagating cancelation. A scheduler may, of course, decide to reschedule the current fiber to be resumed later.</p><p>Because the scheduler does not discontinue a fiber calling <code>current</code>, it is recommended that the caller <a href="#val-check" title="check">checks</a> the cancelation status at the next convenient moment to do so.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-has_forbidden"><a href="#val-has_forbidden" class="anchor"></a><code><span><span class="keyword">val</span> has_forbidden : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> bool</span></code></div><div class="spec-doc"><p><code>has_forbidden fiber</code> determines whether the fiber <a href="#val-forbid"><code>forbid</code></a>s or <a href="#val-permit"><code>permit</code></a>s the scheduler from propagating cancelation to it.</p><p>ℹ️ This is mostly useful in the effect handlers of schedulers.</p><p>⚠️ There is no "reference count" of how many times a fiber has forbidden or permitted propagation of cancelation. Calls to <a href="#val-forbid"><code>forbid</code></a> and <a href="#val-permit"><code>permit</code></a> directly change a single boolean flag.</p><p>⚠️ It is only safe to call <code>has_forbidden</code> from the fiber itself.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-forbid"><a href="#val-forbid" class="anchor"></a><code><span><span class="keyword">val</span> forbid : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> <span><span>(<span>unit <span class="arrow">-></span></span> <span class="type-var">'a</span>)</span> <span class="arrow">-></span></span> <span class="type-var">'a</span></span></code></div><div class="spec-doc"><p><code>forbid fiber thunk</code> tells the scheduler that cancelation must not be propagated to the fiber during the execution of <code>thunk</code>.</p><p>The main use case of <code>forbid</code> is the implementation of concurrent abstractions that may have to <a href="../Trigger/index.html#val-await" title="Trigger.await">await</a> for something, or may need to perform other effects, and must not be canceled while doing so. For example, the wait operation on a condition variable typically reacquires the associated mutex before returning, which may require awaiting for the owner of the mutex to release it.</p><p>ℹ️ <code>forbid</code> does not prevent the fiber or the associated <code>computation</code> from being canceled. It only tells the scheduler not to propagate cancelation to the fiber when it performs effects.</p><p>⚠️ It is only safe to call <code>forbid</code> from the fiber itself.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-permit"><a href="#val-permit" class="anchor"></a><code><span><span class="keyword">val</span> permit : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> <span><span>(<span>unit <span class="arrow">-></span></span> <span class="type-var">'a</span>)</span> <span class="arrow">-></span></span> <span class="type-var">'a</span></span></code></div><div class="spec-doc"><p><code>permit fiber thunk</code> tells the scheduler that cancelation may be propagated to the fiber during the execution of <code>thunk</code>.</p><p>It is possible to <a href="#val-spawn"><code>spawn</code></a> a fiber with cancelation forbidden, which means that cancelation won't be propagated to fiber unless it is explicitly <a href="#val-permit" title="permit">permitted</a> by the fiber at some point.</p><p>⚠️ It is only safe to call <code>permit</code> from the fiber itself.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-is_canceled"><a href="#val-is_canceled" class="anchor"></a><code><span><span class="keyword">val</span> is_canceled : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> bool</span></code></div><div class="spec-doc"><p><code>is_canceled fiber</code> is equivalent to</p><pre class="language-ocaml"><code> not (Fiber.has_forbidden fiber) &&
|
||
let (Packed computation) =
|
||
Fiber.get_computation fiber
|
||
in
|
||
Computation.is_canceled computation</code></pre><p>ℹ️ This is mostly useful in the effect handlers of schedulers.</p><p>⚠️ It is only safe to call <code>is_canceled</code> from the fiber itself.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-canceled"><a href="#val-canceled" class="anchor"></a><code><span><span class="keyword">val</span> canceled : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> <span><span>(exn * <a href="../../../ocaml/Stdlib/Printexc/index.html#type-raw_backtrace">Stdlib.Printexc.raw_backtrace</a>)</span> option</span></span></code></div><div class="spec-doc"><p><code>canceled fiber</code> is equivalent to:</p><pre class="language-ocaml"><code> if Fiber.has_forbidden fiber then
|
||
None
|
||
else
|
||
let (Packed computation) =
|
||
Fiber.get_computation fiber
|
||
in
|
||
Computation.canceled computation</code></pre><p>ℹ️ This is mostly useful in the effect handlers of schedulers.</p><p>⚠️ It is only safe to call <code>canceled</code> from the fiber itself.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-check"><a href="#val-check" class="anchor"></a><code><span><span class="keyword">val</span> check : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> unit</span></code></div><div class="spec-doc"><p><code>check fiber</code> is equivalent to:</p><pre class="language-ocaml"><code> if not (Fiber.has_forbidden fiber) then
|
||
let (Packed computation) =
|
||
Fiber.get_computation fiber
|
||
in
|
||
Computation.check computation</code></pre><p>ℹ️ This is mostly useful for periodically polling the cancelation status during CPU intensive work.</p><p>⚠️ It is only safe to call <code>check</code> from the fiber itself.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-exchange"><a href="#val-exchange" class="anchor"></a><code><span><span class="keyword">val</span> exchange : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> <span><span class="label">forbid</span>:bool <span class="arrow">-></span></span> bool</span></code></div><div class="spec-doc"><p><code>exchange fiber ~forbid</code> sets the bit that tells the scheduler whether to propagate cancelation or not and returns the previous state.</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="#type-t">t</a> <span class="arrow">-></span></span> <span><span class="label">forbid</span>:bool <span class="arrow">-></span></span> unit</span></code></div><div class="spec-doc"><p><code>set fiber ~forbid</code> sets the bit that tells the scheduler whether to propagate cancelation or not.</p></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-FLS"><a href="#module-FLS" class="anchor"></a><code><span><span class="keyword">module</span> <a href="FLS/index.html">FLS</a></span><span> : <span class="keyword">sig</span> ... <span class="keyword">end</span></span></code></div><div class="spec-doc"><p>Fiber local storage</p></div></div><h3 id="interface-for-spawning"><a href="#interface-for-spawning" class="anchor"></a>Interface for spawning</h3><div class="odoc-spec"><div class="spec value anchored" id="val-create_packed"><a href="#val-create_packed" class="anchor"></a><code><span><span class="keyword">val</span> create_packed : <span><span class="label">forbid</span>:bool <span class="arrow">-></span></span> <span><a href="../Computation/index.html#type-packed">Computation.packed</a> <span class="arrow">-></span></span> <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p><code>create_packed ~forbid packed</code> creates a new fiber record.</p></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><span class="label">forbid</span>:bool <span class="arrow">-></span></span> <span><span><span class="type-var">'a</span> <a href="../Computation/index.html#type-t">Computation.t</a></span> <span class="arrow">-></span></span> <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p><code>create ~forbid computation</code> is equivalent to <a href="#val-create_packed" title="create_packed"><code>create_packed ~forbid (Computation.Packed computation)</code></a>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-spawn"><a href="#val-spawn" class="anchor"></a><code><span><span class="keyword">val</span> spawn : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> <span><span>(<span><a href="#type-t">t</a> <span class="arrow">-></span></span> unit)</span> <span class="arrow">-></span></span> unit</span></code></div><div class="spec-doc"><p><code>spawn fiber main</code> starts a new fiber by performing the <a href="#extension-Spawn"><code>Spawn</code></a> effect.</p><p>⚠️ Fiber records must be unique and the caller of <code>spawn</code> must make sure that a specific <a href="#type-fiber" title="fiber">fiber</a> record is not reused. Failure to ensure that fiber records are unique will break concurrent abstractions written on top the the Picos interface.</p><p>⚠️ If the <code>main</code> function raises an exception it is considered a <i>fatal error</i>. A fatal error should effectively either directly exit the program or stop the entire scheduler, without discontinuing existing fibers, and force the invocations of the scheduler on all domains to exit. What this means is that the caller of <code>spawn</code> <i>should</i> ideally arrange for any exception to be handled by <code>main</code>, but, in case that is not practical, it is also possible to allow an exception to propagate out of <code>main</code>, which is then guaranteed to, one way or the other, to stop the entire program. It is not possible to recover from a fatal error.</p><p>ℹ️ The behavior is that</p><ul><li>on OCaml 5, <code>spawn</code> performs the <a href="#extension-Spawn"><code>Spawn</code></a> effect, and</li><li>on OCaml 4, <code>spawn</code> will call the <code>spawn</code> operation of the <a href="../Handler/index.html" title="Handler">current handler</a>.</li></ul></div></div><h3 id="interface-for-structuring"><a href="#interface-for-structuring" class="anchor"></a>Interface for structuring</h3><div class="odoc-spec"><div class="spec value anchored" id="val-get_computation"><a href="#val-get_computation" class="anchor"></a><code><span><span class="keyword">val</span> get_computation : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> <a href="../Computation/index.html#type-packed">Computation.packed</a></span></code></div><div class="spec-doc"><p><code>get_computation fiber</code> returns the computation that the fiber is currently associated with.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-set_computation"><a href="#val-set_computation" class="anchor"></a><code><span><span class="keyword">val</span> set_computation : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> <span><a href="../Computation/index.html#type-packed">Computation.packed</a> <span class="arrow">-></span></span> unit</span></code></div><div class="spec-doc"><p><code>set_computation fiber packed</code> associates the fiber with the specified computation.</p></div></div><h3 id="interface-for-foreign-fiber"><a href="#interface-for-foreign-fiber" class="anchor"></a>Interface for foreign fiber</h3><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">-></span></span> <span><a href="#type-t">t</a> <span class="arrow">-></span></span> bool</span></code></div><div class="spec-doc"><p><code>equal fiber1 fiber2</code> is physical equality for fibers, i.e. it determines whether <code>fiber1</code> and <code>fiber2</code> are one and the same fiber.</p><p>ℹ️ One use case of <code>equal</code> is in the implementation of concurrent primitives like mutexes where it makes sense to check that acquire and release operations are performed by the same fiber.</p></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Maybe"><a href="#module-Maybe" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Maybe/index.html">Maybe</a></span><span> : <span class="keyword">sig</span> ... <span class="keyword">end</span></span></code></div><div class="spec-doc"><p>An unboxed optional <a href="#type-t" title="Fiber.t">fiber</a>.</p></div></div><h3 id="interface-for-schedulers"><a href="#interface-for-schedulers" class="anchor"></a>Interface for schedulers</h3><div class="odoc-spec"><div class="spec value anchored" id="val-try_suspend"><a href="#val-try_suspend" class="anchor"></a><code><span><span class="keyword">val</span> try_suspend :
|
||
<span><a href="#type-t">t</a> <span class="arrow">-></span></span>
|
||
<span><a href="../Trigger/index.html#type-t">Trigger.t</a> <span class="arrow">-></span></span>
|
||
<span><span class="type-var">'x</span> <span class="arrow">-></span></span>
|
||
<span><span class="type-var">'y</span> <span class="arrow">-></span></span>
|
||
<span><span>(<span><a href="../Trigger/index.html#type-t">Trigger.t</a> <span class="arrow">-></span></span> <span><span class="type-var">'x</span> <span class="arrow">-></span></span> <span><span class="type-var">'y</span> <span class="arrow">-></span></span> unit)</span> <span class="arrow">-></span></span>
|
||
bool</span></code></div><div class="spec-doc"><p><code>try_suspend fiber trigger x y resume</code> tries to suspend the <code>fiber</code> to await for the <code>trigger</code> to be <a href="../Trigger/index.html#val-signal" title="Trigger.signal">signaled</a>. If the result is <code>false</code>, then the <code>trigger</code> is guaranteed to be in the signaled state and the fiber should be eventually resumed. If the result is <code>true</code>, then the fiber was suspended, meaning that the <code>trigger</code> will have had the <code>resume</code> action <a href="../Trigger/index.html#val-on_signal" title="Trigger.on_signal">attached</a> to it and the trigger has potentially been <a href="../Computation/index.html#val-try_attach" title="Computation.try_attach">attached</a> to the <code>computation</code> of the fiber.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-unsuspend"><a href="#val-unsuspend" class="anchor"></a><code><span><span class="keyword">val</span> unsuspend : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> <span><a href="../Trigger/index.html#type-t">Trigger.t</a> <span class="arrow">-></span></span> bool</span></code></div><div class="spec-doc"><p><code>unsuspend fiber trigger</code> makes sure that the <code>trigger</code> will not be attached to the computation of the <code>fiber</code>. Returns <code>false</code> in case the fiber has been canceled and propagation of cancelation is not forbidden. Otherwise returns <code>true</code>.</p><ul class="at-tags"><li class="raises"><span class="at-tag">raises</span> <code>Invalid_argument</code> <p>if the trigger is not in the signaled state.</p></li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-resume"><a href="#val-resume" class="anchor"></a><code><span><span class="keyword">val</span> resume :
|
||
<span><a href="#type-t">t</a> <span class="arrow">-></span></span>
|
||
<span><span><span>(<span><span>(exn * <a href="../../../ocaml/Stdlib/Printexc/index.html#type-raw_backtrace">Stdlib.Printexc.raw_backtrace</a>)</span> option</span>, <span class="type-var">'r</span>)</span>
|
||
<a href="../../../ocaml/Stdlib/Effect/Deep/index.html#type-continuation">Stdlib.Effect.Deep.continuation</a></span> <span class="arrow">-></span></span>
|
||
<span class="type-var">'r</span></span></code></div><div class="spec-doc"><p><code>resume fiber k</code> is equivalent to <a href="#val-canceled" title="Fiber.canceled"><code>Effect.Deep.continue k (Fiber.canceled t)</code></a>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-resume_with"><a href="#val-resume_with" class="anchor"></a><code><span><span class="keyword">val</span> resume_with :
|
||
<span><a href="#type-t">t</a> <span class="arrow">-></span></span>
|
||
<span><span><span>(<span><span>(exn * <a href="../../../ocaml/Stdlib/Printexc/index.html#type-raw_backtrace">Stdlib.Printexc.raw_backtrace</a>)</span> option</span>, <span class="type-var">'b</span>)</span>
|
||
<a href="../../../ocaml/Stdlib/Effect/Shallow/index.html#type-continuation">Stdlib.Effect.Shallow.continuation</a></span> <span class="arrow">-></span></span>
|
||
<span><span><span>(<span class="type-var">'b</span>, <span class="type-var">'r</span>)</span> <a href="../../../ocaml/Stdlib/Effect/Shallow/index.html#type-handler">Stdlib.Effect.Shallow.handler</a></span> <span class="arrow">-></span></span>
|
||
<span class="type-var">'r</span></span></code></div><div class="spec-doc"><p><code>resume_with fiber k h</code> is equivalent to <a href="#val-canceled" title="Fiber.canceled"><code>Effect.Shallow.continue_with k (Fiber.canceled t) h</code></a>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-continue"><a href="#val-continue" class="anchor"></a><code><span><span class="keyword">val</span> continue : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> <span><span><span>(<span class="type-var">'v</span>, <span class="type-var">'r</span>)</span> <a href="../../../ocaml/Stdlib/Effect/Deep/index.html#type-continuation">Stdlib.Effect.Deep.continuation</a></span> <span class="arrow">-></span></span> <span><span class="type-var">'v</span> <span class="arrow">-></span></span> <span class="type-var">'r</span></span></code></div><div class="spec-doc"><p><code>continue fiber k v</code> is equivalent to:</p><pre class="language-ocaml"><code> match Fiber.canceled fiber with
|
||
| None -> Effect.Deep.continue k v
|
||
| Some (exn, bt) ->
|
||
Effect.Deep.discontinue_with_backtrace k exn bt</code></pre></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-continue_with"><a href="#val-continue_with" class="anchor"></a><code><span><span class="keyword">val</span> continue_with :
|
||
<span><a href="#type-t">t</a> <span class="arrow">-></span></span>
|
||
<span><span><span>(<span class="type-var">'v</span>, <span class="type-var">'b</span>)</span> <a href="../../../ocaml/Stdlib/Effect/Shallow/index.html#type-continuation">Stdlib.Effect.Shallow.continuation</a></span> <span class="arrow">-></span></span>
|
||
<span><span class="type-var">'v</span> <span class="arrow">-></span></span>
|
||
<span><span><span>(<span class="type-var">'b</span>, <span class="type-var">'r</span>)</span> <a href="../../../ocaml/Stdlib/Effect/Shallow/index.html#type-handler">Stdlib.Effect.Shallow.handler</a></span> <span class="arrow">-></span></span>
|
||
<span class="type-var">'r</span></span></code></div><div class="spec-doc"><p><code>continue_with fiber k v h</code> is equivalent to:</p><pre class="language-ocaml"><code> match Fiber.canceled fiber with
|
||
| None -> Effect.Shallow.continue_with k v h
|
||
| Some (exn, bt) ->
|
||
Effect.Shallow.discontinue_with_backtrace k exn bt h</code></pre></div></div><div class="odoc-spec"><div class="spec type extension anchored" id="extension-decl-Current"><a href="#extension-decl-Current" class="anchor"></a><code><span><span class="keyword">type</span> <a href="../../../ocaml/Stdlib/Effect/index.html#type-t">Stdlib.Effect.t</a> += <span class="keyword">private</span> </span></code><ol><li id="extension-Current" class="def variant extension anchored"><a href="#extension-Current" class="anchor"></a><code><span>| </span><span><span class="extension">Current</span> : <span><a href="#type-t">t</a> <a href="../../../ocaml/Stdlib/Effect/index.html#type-t">Stdlib.Effect.t</a></span></span></code></li></ol></div><div class="spec-doc"><p>Schedulers must handle the <a href="#extension-Current"><code>Current</code></a> effect to implement the behavior of <a href="#val-current"><code>current</code></a>.</p><p>⚠️ The scheduler must eventually resume the fiber without propagating cancelation. This is necessary to allow a fiber to control the propagation of cancelation through the <a href="#type-t" title="t">fiber</a>.</p><p>The scheduler is free to choose which ready fiber to resume next. However, in typical use cases of <a href="#val-current"><code>current</code></a> it makes sense to give priority to the fiber performing <a href="#extension-Current"><code>Current</code></a>, but this is not required.</p></div></div><div class="odoc-spec"><div class="spec type extension anchored" id="extension-decl-Yield"><a href="#extension-decl-Yield" class="anchor"></a><code><span><span class="keyword">type</span> <a href="../../../ocaml/Stdlib/Effect/index.html#type-t">Stdlib.Effect.t</a> += <span class="keyword">private</span> </span></code><ol><li id="extension-Yield" class="def variant extension anchored"><a href="#extension-Yield" class="anchor"></a><code><span>| </span><span><span class="extension">Yield</span> : <span>unit <a href="../../../ocaml/Stdlib/Effect/index.html#type-t">Stdlib.Effect.t</a></span></span></code></li></ol></div><div class="spec-doc"><p>Schedulers must handle the <a href="#extension-Yield"><code>Yield</code></a> effect to implement the behavior of <a href="#val-yield"><code>yield</code></a>.</p><p>In case the fiber permits propagation of cancelation and the computation associated with the fiber has been canceled the scheduler is free to discontinue the fiber immediately.</p><p>The scheduler should give priority to running other ready fibers before resuming the fiber performing <a href="#extension-Yield"><code>Yield</code></a>. A scheduler that always immediately resumes the fiber performing <a href="#extension-Yield"><code>Yield</code></a> may prevent an otherwise valid program from making progress.</p></div></div><div class="odoc-spec"><div class="spec type extension anchored" id="extension-decl-Spawn"><a href="#extension-decl-Spawn" class="anchor"></a><code><span><span class="keyword">type</span> <a href="../../../ocaml/Stdlib/Effect/index.html#type-t">Stdlib.Effect.t</a> += <span class="keyword">private</span> </span></code><ol><li id="extension-Spawn" class="def variant extension anchored"><a href="#extension-Spawn" class="anchor"></a><code><span>| </span><span><span class="extension">Spawn</span> : </span><span>{</span></code><ol><li id="module-Fiber.fiber" class="def record field anchored"><a href="#module-Fiber.fiber" class="anchor"></a><code><span>fiber : <a href="#type-t">t</a>;</span></code></li><li id="module-Fiber.main" class="def record field anchored"><a href="#module-Fiber.main" class="anchor"></a><code><span>main : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> unit;</span></code></li></ol><code><span>}</span><span> <span class="arrow">-></span> <span>unit <a href="../../../ocaml/Stdlib/Effect/index.html#type-t">Stdlib.Effect.t</a></span></span></code></li></ol></div><div class="spec-doc"><p>Schedulers must handle the <a href="#extension-Spawn"><code>Spawn</code></a> effect to implement the behavior of <a href="#val-spawn"><code>spawn</code></a>.</p><p>In case the fiber permits propagation of cancelation and the computation associated with the fiber has been canceled the scheduler is free to discontinue the fiber immediately before spawning new fibers.</p><p>The scheduler is free to run the newly created fiber on any domain and decide which fiber to give priority to.</p><p>⚠️ The scheduler should guarantee that, when <code>Spawn</code> returns normally, the given <code>main</code> will eventually be called by the scheduler and, when <code>Spawn</code> raises an exception, the <code>main</code> will not be called. In other words, <code>Spawn</code> should check cancelation just once and be all or nothing. Furthermore, in case a newly spawned fiber is canceled before its main is called, the scheduler must still call the main. This allows a program to ensure, i.e. keep track of, that all fibers it spawns are terminated properly and any resources transmitted to spawned fibers will be disposed properly.</p></div></div><h3 id="design-rationale"><a href="#design-rationale" class="anchor"></a>Design rationale</h3><p>The idea is that fibers correspond 1-to-1 with independent threads of execution. This allows a fiber to non-atomically store state related to a thread of execution.</p><p>The status of whether propagation of cancelation is forbidden or permitted could be stored in the <a href="FLS/index.html" title="FLS">fiber local storage</a>. The justification for storing it directly with the fiber is that the implementation of some key synchronization and communication mechanisms, such as condition variables, requires the capability.</p><p>No integer fiber id is provided by default. It would seem that for most intents and purposes the identity of the fiber is sufficient. <a href="FLS/index.html" title="FLS">Fiber local storage</a> can be used to implement a fiber id or e.g. a fiber hash.</p><p>The <a href="FLS/index.html" title="FLS">fiber local storage</a> is designed for the purpose of extending fibers and to be as fast as possible. It is not intended for application programming.</p><p><a href="#extension-Yield"><code>Yield</code></a> is provided as a separate effect to specifically communicate the intent that the current fiber should be rescheduled. This allows all the other effect handlers more freedom in choosing which fiber to schedule next.</p></div></body></html>
|