From 61ea820fd49dbcbeeb1a52b1d192d97a3f1949c5 Mon Sep 17 00:00:00 2001 From: c-cube Date: Thu, 3 Oct 2024 17:10:12 +0000 Subject: [PATCH] deploy: 9b6a1d37189330a4554089febcd1140e50664eca --- backoff/_doc-dir/CHANGES.md | 4 ++-- picos/Picos/Fiber/FLS/index.html | 2 +- picos/Picos/index.html | 14 ++++++++++++-- picos_std/Picos_std_structured/Promise/index.html | 2 +- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/backoff/_doc-dir/CHANGES.md b/backoff/_doc-dir/CHANGES.md index 02a66c93..7e01cc5d 100644 --- a/backoff/_doc-dir/CHANGES.md +++ b/backoff/_doc-dir/CHANGES.md @@ -1,6 +1,6 @@ -# Release notes +## 0.1.1 -All notable changes to this project will be documented in this file. +- Ported to 4.12 and optimized for size (@polytypic) ## 0.1.0 diff --git a/picos/Picos/Fiber/FLS/index.html b/picos/Picos/Fiber/FLS/index.html index c705a9b1..2caea212 100644 --- a/picos/Picos/Fiber/FLS/index.html +++ b/picos/Picos/Fiber/FLS/index.html @@ -1,2 +1,2 @@ -FLS (picos.Picos.Fiber.FLS)

Module Fiber.FLS

Fiber local storage

Fiber local storage is intended for use as a low overhead storage mechanism for fiber extensions. For example, one might associate a priority value with each fiber for a scheduler that uses a priority queue or one might use FLS to store unique id values for fibers.

type fiber := t

Destructively substituted alias for Fiber.t.

type 'a t

Represents a key for storing values of type 'a in storage associated with fibers.

val create : unit -> 'a t

new_key initial allocates a new key for associating values in storage associated with fibers. The initial value for every fiber is either the given Constant or is Computed with the given function. If the initial value is a constant, no value needs to be stored unless the value is explicitly updated.

⚠️ New keys should not be created dynamically.

exception Not_set

Raised by get_exn in case value has not been set.

val get_exn : fiber -> 'a t -> 'a

get_exn fiber key returns the value associated with the key in the storage associated with the fiber or raises Not_set using raise_notrace.

⚠️ It is only safe to call get_exn from the fiber itself or when the fiber is known not to be running.

val get : fiber -> 'a t -> default:'a -> 'a

get fiber key ~default returns the value associated with the key in the storage associated with the fiber or the default value.

⚠️ It is only safe to call get from the fiber itself or when the fiber is known not to be running.

val set : fiber -> 'a t -> 'a -> unit

set fiber key value sets the value associated with the key to the given value in the storage associated with the fiber.

⚠️ It is only safe to call set from the fiber itself or when the fiber is known not to be running.

val remove : fiber -> 'a t -> unit

remove fiber key removes the value, if any, associated with the key from the storage associated with the fiber.

⚠️ It is only safe to call remove from the fiber itself or when the fiber is known not to be running.

+FLS (picos.Picos.Fiber.FLS)

Module Fiber.FLS

Fiber local storage

Fiber local storage is intended for use as a low overhead storage mechanism for fiber extensions. For example, one might associate a priority value with each fiber for a scheduler that uses a priority queue or one might use FLS to store unique id values for fibers.

type fiber := t

Destructively substituted alias for Fiber.t.

type 'a t

Represents a key for storing values of type 'a in storage associated with fibers.

val create : unit -> 'a t

new_key initial allocates a new key for associating values in storage associated with fibers. The initial value for every fiber is either the given Constant or is Computed with the given function. If the initial value is a constant, no value needs to be stored unless the value is explicitly updated.

⚠️ New keys should not be created dynamically.

exception Not_set

Raised by get_exn in case value has not been set.

val get_exn : fiber -> 'a t -> 'a

get_exn fiber key returns the value associated with the key in the storage associated with the fiber or raises Not_set using raise_notrace.

⚠️ It is only safe to call get_exn from the fiber itself or when the fiber is known not to be running.

val get : fiber -> 'a t -> default:'a -> 'a

get fiber key ~default returns the value associated with the key in the storage associated with the fiber or the default value.

⚠️ It is only safe to call get from the fiber itself or when the fiber is known not to be running.

val set : fiber -> 'a t -> 'a -> unit

set fiber key value sets the value associated with the key to the given value in the storage associated with the fiber.

⚠️ It is only safe to call set from the fiber itself or when the fiber is known not to be running.

val remove : fiber -> 'a t -> unit

remove fiber key removes the value, if any, associated with the key from the storage associated with the fiber.

⚠️ It is only safe to call remove from the fiber itself or when the fiber is known not to be running.

val reserve : fiber -> 'a t -> unit

reserve fiber key ensures that sufficient space has been allocated to associate a value with the specified key such that a subsequent set with the key will not allocate.

ℹ️ This can be used to optimize the population of the FLS and to avoid performing memory allocations in critical sections.

⚠️ It is only safe to call reserve from the fiber itself or when the fiber is known not to be running.

diff --git a/picos/Picos/index.html b/picos/Picos/index.html index 87fabd4f..0a19bdaa 100644 --- a/picos/Picos/index.html +++ b/picos/Picos/index.html @@ -1,6 +1,16 @@ -Picos (picos.Picos)

Module Picos

A systems programming interface between effects based schedulers and concurrent abstractions.

This is essentially an interface between schedulers and concurrent abstractions that need to communicate with a scheduler. Perhaps an enlightening analogy is to say that this is the POSIX of effects based schedulers.

ℹ️ Picos, i.e. this module, is not intended to be an application level concurrent programming library or framework. If you are looking for a library or framework for programming concurrent applications, then this module is probably not what you are looking for.

The architecture of Picos

The core concepts of Picos are

that are implemented in terms of the effects

that can be used to implement many kinds of higher level concurrent programming facilities.

Understanding cancelation

A central idea of Picos is to provide a collection of building blocks for parallelism safe cancelation. Consider the following characteristic example:

Mutex.protect mutex begin fun () ->
+Picos (picos.Picos)

Module Picos

A systems programming interface between effects based schedulers and concurrent abstractions.

This is essentially an interface between schedulers and concurrent abstractions that need to communicate with a scheduler. Perhaps an enlightening analogy is to say that this is the POSIX of effects based schedulers.

ℹ️ Picos, i.e. this module, is not intended to be an application level concurrent programming library or framework. If you are looking for a library or framework for programming concurrent applications, then this module is probably not what you are looking for.

The architecture of Picos

The core concepts of Picos are

  • Trigger — ability to await for a signal,
  • Computation — a cancelable computation, and
  • Fiber — an independent thread of execution,

that are implemented in terms of the effects

that can be used to implement many kinds of higher level concurrent programming facilities.

Understanding cancelation

A central idea of Picos is to provide a collection of building blocks for parallelism safe cancelation.

Consider the following motivating example:

Mutex.protect mutex begin fun () ->
   while true do
     Condition.wait condition mutex
   done
-end

Assume that the fiber executing the above computation might be canceled, at any point, by another fiber running in parallel. How could that be done both effectively and safely?

  • To be effective, cancelation should take effect as soon as possible. In this case, cancelation should take effect even during the Mutex.lock inside Mutex.protect and the Condition.wait operations when the fiber might be in a suspended state awaiting for a signal to continue.
  • To be safe, cancelation should not leave the program in an invalid state or cause the program to leak memory. In this case, the ownership of the mutex must be transferred to the next fiber or be left unlocked and no references to unused objects must be left in the mutex or the condition variable.

Picos allows Mutex and Condition to be implemented such that cancelation may safely take effect at or during calls to Mutex.lock and Condition.wait.

Cancelation in Picos

The Fiber concept in Picos corresponds to an independent thread of execution. A fiber may explicitly forbid or permit the scheduler from propagating cancelation to it. This is important for the implementation of some key concurrent abstractions such as condition variables, where it is necessary to forbid cancelation when the associated mutex is reacquired.

Each fiber has an associated Computation at all times. A computation is something that needs to be completed either by returning a value through it or by canceling it with an exception. To cancel a fiber one cancels the computation associated with the fiber or any computation whose cancelation is propagated to the computation associated with the fiber.

Before a computation has been completed, it is also possible to attach a Trigger to the computation and also to later detach the trigger from the computation. A trigger attached to a computation is signaled as the computation is completed.

The Trigger concept in Picos is what allows a fiber to be suspended and later resumed. A fiber can create a trigger, add it to any shared data structure(s), and await for the trigger to be signaled. The await operation, which is implemented by the scheduler, also, in case the fiber permits cancelation, attaches the trigger to the computation of the fiber when it suspends the fiber. This is what allows a fiber to be resumed via cancelation of the computation.

The return value of await tells whether the fiber was resumed normally or due to being canceled and the caller then needs to properly handle either case. After being canceled, depending on the concurrent abstraction being implemented, the caller might need to e.g. remove references to the trigger from the shared data structures, cancel asynchronous IO operations, or transfer ownership of a mutex to the next fiber in the queue of the mutex.

Modules reference

For the examples in this document, we first open the Picos module

open Picos

as well as the Picos_std_structured library,

open Picos_std_structured

which we will be using for managing fibers in some of the examples, and define a simple scheduler on OCaml 4

let run main = Picos_mux_thread.run main

using the basic thread based scheduler and on OCaml 5

let run main = Picos_mux_random.run_on ~n_domains:2 main

using the randomized effects based scheduler that come with Picos as samples.

Core modules

module Trigger : sig ... end

Ability to await for a signal.

module Computation : sig ... end

A cancelable computation.

module Fiber : sig ... end

An independent thread of execution.

module Handler : sig ... end

Handler for the effects based operations of Picos for OCaml 4.

+end

Assume that the fiber executing the above computation might be canceled, at any point, by another fiber running in parallel. How could that be done ensuring both safety and liveness?

Here is another motivating example:

(* ... allocate resources ... *)
+Fun.protect ~finally begin fun () ->
+  Flock.join_after begin fun () ->
+    (* ... *)
+    Flock.fork begin fun () ->
+      (* ... may use resources ... *)
+    end;
+    (* ... *)
+  end;
+  (* ... resources no longer used ... *)
+end

The idea is that the main or parent fiber allocates some resources, which are then used by child fibers running in parallel. What should happen when the main fiber gets canceled? We again have both safety and liveness concerns:

Picos is designed to allow the above motivating examples and more to be implemented correctly addressing both safety and liveness.

Cancelation in Picos

The Fiber concept in Picos corresponds to an independent thread of execution. A fiber may explicitly forbid or permit the scheduler from propagating cancelation to it. This is important for the implementation of some key concurrent abstractions such as condition variables, where it is necessary to forbid cancelation when the associated mutex is reacquired.

Each fiber has an associated Computation at all times. A computation is something that needs to be completed either by returning a value through it or by canceling it with an exception. To cancel a fiber one cancels the computation associated with the fiber or any computation whose cancelation is propagated to the computation associated with the fiber.

Before a computation has been completed, it is also possible to attach a Trigger to the computation and also to later detach the trigger from the computation. A trigger attached to a computation is signaled as the computation is completed.

The Trigger concept in Picos is what allows a fiber to be suspended and later resumed. A fiber can create a trigger, add it to any shared data structure(s), and await for the trigger to be signaled. The await operation, which is implemented by the scheduler, also, in case the fiber permits cancelation, attaches the trigger to the computation of the fiber when it suspends the fiber. This is what allows a fiber to be resumed via cancelation of the computation.

The return value of await tells whether the fiber was resumed normally or due to being canceled and the caller then needs to properly handle either case. After being canceled, depending on the concurrent abstraction being implemented, the caller might need to e.g. remove references to the trigger from the shared data structures, cancel asynchronous IO operations, or transfer ownership of a mutex to the next fiber in the queue of the mutex.

Modules reference

For the examples in this document, we first open the Picos module

open Picos

as well as the Picos_std_structured library,

open Picos_std_structured

which we will be using for managing fibers in some of the examples, and define a simple scheduler on OCaml 4

let run main = Picos_mux_thread.run main

using the basic thread based scheduler and on OCaml 5

let run main = Picos_mux_random.run_on ~n_domains:2 main

using the randomized effects based scheduler that come with Picos as samples.

Core modules

module Trigger : sig ... end

Ability to await for a signal.

module Computation : sig ... end

A cancelable computation.

module Fiber : sig ... end

An independent thread of execution.

module Handler : sig ... end

Handler for the effects based operations of Picos for OCaml 4.

diff --git a/picos_std/Picos_std_structured/Promise/index.html b/picos_std/Picos_std_structured/Promise/index.html index 1f800c3d..9e8ec63e 100644 --- a/picos_std/Picos_std_structured/Promise/index.html +++ b/picos_std/Picos_std_structured/Promise/index.html @@ -1,2 +1,2 @@ -Promise (picos_std.Picos_std_structured.Promise)

Module Picos_std_structured.Promise

A cancelable promise.

ℹ️ In addition to using a promise to concurrently compute and return a value, a cancelable promise can also represent a concurrent fiber that will continue until it is explicitly canceled.

type !'a t

Represents a promise to return value of type 'a.

val of_value : 'a -> 'a t

of_value value returns a constant completed promise that returns the given value.

ℹ️ Promises can also be created in the scope of a Bundle or a Flock.

val await : 'a t -> 'a

await promise awaits until the promise has completed and either returns the value that the evaluation of the promise returned, raises the exception that the evaluation of the promise raised, or raises the Terminate exception in case the promise has been canceled.

val completed : 'a t -> 'a Picos_std_event.Event.t

completed promise returns an event that can be committed to once the promise has completed.

val is_running : 'a t -> bool

is_running promise determines whether the completion of the promise is still pending.

val try_terminate : ?callstack:int -> 'a t -> bool

try_terminate promise tries to terminate the promise by canceling it with the Terminate exception and returns true in case of success and false in case the promise had already completed, i.e. either returned, raised, or canceled.

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

val terminate : ?callstack:int -> 'a t -> unit

terminate promise is equivalent to try_terminate promise |> ignore.

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

terminate_after ~seconds promise arranges to terminate the promise by canceling it with the Terminate exception after the specified timeout in seconds.

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

+Promise (picos_std.Picos_std_structured.Promise)

Module Picos_std_structured.Promise

A cancelable promise.

ℹ️ In addition to using a promise to concurrently compute and return a value, a cancelable promise can also represent a concurrent fiber that will continue until it is explicitly canceled.

⚠️ Canceling a promise does not immediately terminate the fiber or wait for the fiber working to complete the promise to terminate. Constructs like Bundle.join_after and Flock.join_after only guarantee that all fibers forked within their scope have terminated before they return or raise. The reason for this design choice in this library is that synchronization is expensive and delaying synchronization to the join operation is typically sufficient and amortizes the cost.

type !'a t

Represents a promise to produce a value of type 'a.

val of_value : 'a -> 'a t

of_value value returns a constant completed promise that returns the given value.

ℹ️ Promises can also be created in the scope of a Bundle or a Flock.

val await : 'a t -> 'a

await promise awaits until the promise has completed and either returns the value that the evaluation of the promise returned, raises the exception that the evaluation of the promise raised, or raises the Terminate exception in case the promise has been canceled.

⚠️ The fiber corresponding to a canceled promise is not guaranteed to have terminated at the point await raises.

val completed : 'a t -> 'a Picos_std_event.Event.t

completed promise returns an event that can be committed to once the promise has completed.

val is_running : 'a t -> bool

is_running promise determines whether the completion of the promise is still pending.

val try_terminate : ?callstack:int -> 'a t -> bool

try_terminate promise tries to terminate the promise by canceling it with the Terminate exception and returns true in case of success and false in case the promise had already completed, i.e. either returned, raised, or canceled.

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

val terminate : ?callstack:int -> 'a t -> unit

terminate promise is equivalent to try_terminate promise |> ignore.

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

terminate_after ~seconds promise arranges to terminate the promise by canceling it with the Terminate exception after the specified timeout in seconds.

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