Private.Fiber_context
Every fiber has an associated context.
val make_root : unit -> t
Make a new root context for a new domain.
val destroy : t -> unit
destroy t
removes t
from its cancellation context.
The Cancel
module describes the user's view of cancellation.
Internally, when the user calls a primitive operation that needs to block the fiber, the Suspend callback
effect is performed. This suspends the fiber and calls callback
from the scheduler's context, passing it the suspended fiber's context. If the operation can be cancelled, the callback should use set_cancel_fn
to register a cancellation function.
There are two possible outcomes for the operation: it may complete normally, or it may be cancelled. If it is cancelled then the registered cancellation function is called. This function will always be called from the fiber's own domain, but care must be taken if the operation could be completed by another domain at the same time.
Consider the case of Stream.take
, which can be fulfilled by a Stream.add
from another domain. We want to ensure that either the item is removed from the stream and returned to the waiting fiber, or that the operation is cancelled and the item is not removed from the stream.
Therefore, cancelling and completing both need to update an atomic value (with Atomic.compare_and_set
) so that only one can succeed. The case where Stream.take
succeeds before cancellation:
Suspend
and is suspended. The callback sets a cancel function and registers a waiter on the stream.take
uncancellable) and begins resuming the fiber with the new item.The case of cancellation winning the race:
Suspend
and is suspended. The callback sets a cancel function and registers a waiter on the stream.Note: A fiber will only have a cancel function set while it is suspended.
val set_cancel_fn : t -> (exn -> unit) -> unit
set_cancel_fn t fn
sets fn
as the fiber's cancel function.
If t
's cancellation context is cancelled, the function is called. It should attempt to make the current operation finish quickly, either with a successful result or by raising the given exception.
Just before being called, the fiber's cancel function is replaced with ignore
so that fn
cannot be called twice.
On success, the cancel function is cleared automatically when Suspend.enter
returns, but for single-domain operations you may like to call clear_cancel_fn
manually to remove it earlier.
fn
will be called from t
's domain (from the fiber that called cancel
).
fn
must not switch fibers. If it did, this could happen:
fn
returns.val clear_cancel_fn : t -> unit
clear_cancel_fn t
is set_cancel_fn t ignore
.
This must only be called from the fiber's own domain.
For single-domain operations, it can be useful to call this manually as soon as the operation succeeds (i.e. when the fiber is added to the run-queue) to prevent the cancel function from being called.
For operations where another domain may resume the fiber, your cancel function will need to cope with being called after the operation has succeeded. In that case you should not call clear_cancel_fn
. The backend will do it automatically just before resuming your fiber.
val get_error : t -> exn option
get_error t
is Cancel.get_error (cancellation_context t)