Module Picos_std_structured.Control

Basic control operations and exceptions for structured concurrency.

exception Terminate

An exception that is used to signal fibers, typically by canceling them, that they should terminate by letting the exception propagate.

ℹ️ Within this library, the Terminate exception does not, by itself, indicate an error. Raising it inside a fiber forked within the structured concurrency constructs of this library simply causes the relevant part of the tree of fibers to be terminated.

⚠️ If Terminate is raised in the main fiber of a Bundle, and no other exceptions are raised within any fiber inside the bundle, the bundle will then, of course, raise the Terminate exception after all of the fibers have been terminated.

exception Errors of (exn * Stdlib.Printexc.raw_backtrace) list

An exception that can be used to collect exceptions, typically indicating errors, from multiple fibers.

ℹ️ The Terminate exception is not considered an error within this library and the structuring constructs do not include it in the list of Errors.

val raise_if_canceled : unit -> unit

raise_if_canceled () checks whether the current fiber has been canceled and if so raises the exception that the fiber was canceled with.

ℹ️ Within this library fibers are canceled using the Terminate exception.

val yield : unit -> unit

yield () asks the current fiber to be rescheduled.

val sleep : seconds:float -> unit

sleep ~seconds suspends the current fiber for the specified number of seconds.

val protect : (unit -> 'a) -> 'a

protect thunk forbids propagation of cancelation for the duration of thunk ().

ℹ️ Many operations are cancelable. In particular, anything that might suspend the current fiber to await for something should typically be cancelable. Operations that release resources may sometimes also be cancelable and calls of such operations should typically be protected to ensure that resources will be properly released. Forbidding propagation of cancelation may also be required when a sequence of cancelable operations must be performed.

ℹ️ With the constructs provided by this library it is not possible to prevent a fiber from being canceled, but it is possible for a fiber to forbid the scheduler from propagating cancelation to the fiber.

val block : unit -> 'a

block () suspends the current fiber until it is canceled at which point the cancelation exception will be raised.

  • raises Invalid_argument

    in case propagation of cancelation has been forbidden.

  • raises Sys_error

    in case the underlying computation of the fiber is forced to return during block. This is only possible when the fiber has been spawned through another library.

val terminate_after : ?callstack:int -> seconds:float -> (unit -> 'a) -> 'a

terminate_after ~seconds thunk arranges to terminate the execution of thunk on the current fiber after the specified timeout in seconds.

Using terminate_after one can attempt any blocking operation that supports cancelation with a timeout. For example, one could try to read an Ivar with a timeout

let peek_in ~seconds ivar =
  match
    Control.terminate_after ~seconds @@ fun () -> Ivar.read ivar
  with
  | value -> Some value
  | exception Control.Terminate -> None

or one could try to connect a socket with a timeout

let try_connect_in ~seconds socket sockaddr =
  match
    Control.terminate_after ~seconds @@ fun () ->
    Unix.connect socket sockaddr
  with
  | () -> true
  | exception Control.Terminate -> false

using the Picos_io.Unix module.

The optional callstack argument specifies the number of callstack entries to capture with the Terminate exception. The default is 0.

As an example, terminate_after could be implemented using Bundle as follows:

let terminate_after ?callstack ~seconds thunk =
  Bundle.join_after @@ fun bundle ->
  Bundle.terminate_after ?callstack ~seconds bundle;
  thunk ()