From 41b180fdefd31f1addd94707d92ec866e8214162 Mon Sep 17 00:00:00 2001 From: c-cube Date: Tue, 20 Feb 2024 17:03:17 +0000 Subject: [PATCH] deploy: df8b284a0d8ba70f82904d5b7a80f187e69fea72 --- dev/index.html | 2 +- dev/lwt/Lwt/Exception_filter/index.html | 2 + .../Infix/Let_syntax/Open_on_rhs/index.html | 2 + dev/lwt/Lwt/Infix/Let_syntax/index.html | 2 + dev/lwt/Lwt/Infix/index.html | 14 + .../Let_syntax/Open_on_rhs/index.html | 2 + dev/lwt/Lwt/Let_syntax/Let_syntax/index.html | 2 + dev/lwt/Lwt/Let_syntax/index.html | 2 + dev/lwt/Lwt/Syntax/index.html | 2 + dev/lwt/Lwt/index.html | 356 +++++ dev/lwt/Lwt_bytes/index.html | 42 + dev/lwt/Lwt_condition/index.html | 2 + dev/lwt/Lwt_config/index.html | 2 + dev/lwt/Lwt_engine/Ev_backend/index.html | 2 + .../Versioned/class-libev_1/index.html | 2 + .../Versioned/class-libev_2/index.html | 2 + dev/lwt/Lwt_engine/Versioned/index.html | 2 + dev/lwt/Lwt_engine/class-abstract/index.html | 9 + dev/lwt/Lwt_engine/class-libev/index.html | 2 + .../Lwt_engine/class-poll_based/index.html | 4 + dev/lwt/Lwt_engine/class-select/index.html | 6 + .../Lwt_engine/class-select_based/index.html | 5 + dev/lwt/Lwt_engine/class-type-t/index.html | 6 + dev/lwt/Lwt_engine/index.html | 2 + dev/lwt/Lwt_features/index.html | 2 + dev/lwt/Lwt_fmt/index.html | 20 + dev/lwt/Lwt_gc/index.html | 2 + dev/lwt/Lwt_io/BE/index.html | 2 + dev/lwt/Lwt_io/LE/index.html | 2 + dev/lwt/Lwt_io/Versioned/index.html | 15 + dev/lwt/Lwt_io/index.html | 125 ++ .../Lwt_io/module-type-NumberIO/index.html | 2 + dev/lwt/Lwt_list/index.html | 2 + dev/lwt/Lwt_main/Enter_iter_hooks/index.html | 2 + dev/lwt/Lwt_main/Exit_hooks/index.html | 2 + dev/lwt/Lwt_main/Leave_iter_hooks/index.html | 2 + dev/lwt/Lwt_main/index.html | 4 + dev/lwt/Lwt_main/module-type-Hooks/index.html | 2 + dev/lwt/Lwt_mutex/index.html | 2 + dev/lwt/Lwt_mvar/index.html | 2 + dev/lwt/Lwt_pool/index.html | 22 + .../Lwt_pqueue/Make/argument-1-Ord/index.html | 2 + dev/lwt/Lwt_pqueue/Make/index.html | 2 + dev/lwt/Lwt_pqueue/index.html | 2 + .../module-type-OrderedType/index.html | 2 + dev/lwt/Lwt_pqueue/module-type-S/index.html | 2 + dev/lwt/Lwt_preemptive/index.html | 2 + dev/lwt/Lwt_process/class-process/index.html | 2 + .../Lwt_process/class-process_full/index.html | 2 + .../Lwt_process/class-process_in/index.html | 2 + .../Lwt_process/class-process_none/index.html | 2 + .../Lwt_process/class-process_out/index.html | 2 + dev/lwt/Lwt_process/index.html | 173 +++ dev/lwt/Lwt_result/Infix/index.html | 2 + .../Let_syntax/Open_on_rhs/index.html | 2 + .../Let_syntax/Let_syntax/index.html | 2 + dev/lwt/Lwt_result/Let_syntax/index.html | 2 + dev/lwt/Lwt_result/Syntax/index.html | 2 + dev/lwt/Lwt_result/index.html | 2 + dev/lwt/Lwt_seq/index.html | 2 + dev/lwt/Lwt_sequence/index.html | 2 + .../class-type-bounded_push/index.html | 2 + dev/lwt/Lwt_stream/index.html | 21 + dev/lwt/Lwt_switch/index.html | 16 + dev/lwt/Lwt_sys/index.html | 2 + .../Lwt_throttle/Make/argument-1-H/index.html | 2 + dev/lwt/Lwt_throttle/Make/index.html | 2 + dev/lwt/Lwt_throttle/index.html | 2 + dev/lwt/Lwt_throttle/module-type-S/index.html | 2 + dev/lwt/Lwt_timeout/index.html | 2 + dev/lwt/Lwt_unix/IO_vectors/index.html | 4 + dev/lwt/Lwt_unix/LargeFile/index.html | 2 + dev/lwt/Lwt_unix/Versioned/index.html | 9 + dev/lwt/Lwt_unix/index.html | 76 ++ dev/lwt/_doc-dir/CHANGES | 1145 +++++++++++++++++ dev/lwt/_doc-dir/LICENSE.md | 19 + dev/lwt/_doc-dir/README.md | 187 +++ dev/lwt/_doc-dir/odoc-pages/index.mld | 131 ++ dev/lwt/index.html | 25 + dev/moonpool-lwt/Moonpool_lwt/IO/index.html | 2 + .../IO_in/class-type-t/index.html | 2 + .../Moonpool_lwt/IO_in/index.html | 6 + .../IO_out/class-type-t/index.html | 2 + .../Moonpool_lwt/IO_out/index.html | 8 + .../Moonpool_lwt/TCP_client/index.html | 5 + .../Moonpool_lwt/TCP_server/index.html | 14 + dev/moonpool-lwt/Moonpool_lwt/index.html | 2 + dev/moonpool-lwt/Moonpool_lwt__/index.html | 2 + .../Moonpool_lwt__Base/index.html | 2 + dev/moonpool-lwt/Moonpool_lwt__IO/index.html | 2 + .../Moonpool_lwt__IO_in/index.html | 2 + .../Moonpool_lwt__IO_out/index.html | 2 + .../Moonpool_lwt__Tcp_client/index.html | 2 + .../Moonpool_lwt__Tcp_server/index.html | 2 + dev/moonpool-lwt/_doc-dir/CHANGES.md | 103 ++ dev/moonpool-lwt/_doc-dir/README.md | 313 +++++ dev/moonpool-lwt/index.html | 2 + .../For_runner_implementors/index.html | 2 +- dev/moonpool/Moonpool/Fifo_pool/index.html | 12 +- dev/moonpool/Moonpool/Fut/index.html | 4 +- .../For_runner_implementors/index.html | 2 +- .../Moonpool/Immediate_runner/index.html | 12 +- .../Runner/For_runner_implementors/index.html | 2 +- dev/moonpool/Moonpool/Runner/index.html | 12 +- .../For_runner_implementors/index.html | 2 +- dev/moonpool/Moonpool/Ws_pool/index.html | 12 +- dev/moonpool/Moonpool/index.html | 10 +- dev/moonpool/Moonpool_fib/Fiber/index.html | 2 +- .../Moonpool_private/Tracing_/index.html | 2 +- 109 files changed, 3030 insertions(+), 61 deletions(-) create mode 100644 dev/lwt/Lwt/Exception_filter/index.html create mode 100644 dev/lwt/Lwt/Infix/Let_syntax/Open_on_rhs/index.html create mode 100644 dev/lwt/Lwt/Infix/Let_syntax/index.html create mode 100644 dev/lwt/Lwt/Infix/index.html create mode 100644 dev/lwt/Lwt/Let_syntax/Let_syntax/Open_on_rhs/index.html create mode 100644 dev/lwt/Lwt/Let_syntax/Let_syntax/index.html create mode 100644 dev/lwt/Lwt/Let_syntax/index.html create mode 100644 dev/lwt/Lwt/Syntax/index.html create mode 100644 dev/lwt/Lwt/index.html create mode 100644 dev/lwt/Lwt_bytes/index.html create mode 100644 dev/lwt/Lwt_condition/index.html create mode 100644 dev/lwt/Lwt_config/index.html create mode 100644 dev/lwt/Lwt_engine/Ev_backend/index.html create mode 100644 dev/lwt/Lwt_engine/Versioned/class-libev_1/index.html create mode 100644 dev/lwt/Lwt_engine/Versioned/class-libev_2/index.html create mode 100644 dev/lwt/Lwt_engine/Versioned/index.html create mode 100644 dev/lwt/Lwt_engine/class-abstract/index.html create mode 100644 dev/lwt/Lwt_engine/class-libev/index.html create mode 100644 dev/lwt/Lwt_engine/class-poll_based/index.html create mode 100644 dev/lwt/Lwt_engine/class-select/index.html create mode 100644 dev/lwt/Lwt_engine/class-select_based/index.html create mode 100644 dev/lwt/Lwt_engine/class-type-t/index.html create mode 100644 dev/lwt/Lwt_engine/index.html create mode 100644 dev/lwt/Lwt_features/index.html create mode 100644 dev/lwt/Lwt_fmt/index.html create mode 100644 dev/lwt/Lwt_gc/index.html create mode 100644 dev/lwt/Lwt_io/BE/index.html create mode 100644 dev/lwt/Lwt_io/LE/index.html create mode 100644 dev/lwt/Lwt_io/Versioned/index.html create mode 100644 dev/lwt/Lwt_io/index.html create mode 100644 dev/lwt/Lwt_io/module-type-NumberIO/index.html create mode 100644 dev/lwt/Lwt_list/index.html create mode 100644 dev/lwt/Lwt_main/Enter_iter_hooks/index.html create mode 100644 dev/lwt/Lwt_main/Exit_hooks/index.html create mode 100644 dev/lwt/Lwt_main/Leave_iter_hooks/index.html create mode 100644 dev/lwt/Lwt_main/index.html create mode 100644 dev/lwt/Lwt_main/module-type-Hooks/index.html create mode 100644 dev/lwt/Lwt_mutex/index.html create mode 100644 dev/lwt/Lwt_mvar/index.html create mode 100644 dev/lwt/Lwt_pool/index.html create mode 100644 dev/lwt/Lwt_pqueue/Make/argument-1-Ord/index.html create mode 100644 dev/lwt/Lwt_pqueue/Make/index.html create mode 100644 dev/lwt/Lwt_pqueue/index.html create mode 100644 dev/lwt/Lwt_pqueue/module-type-OrderedType/index.html create mode 100644 dev/lwt/Lwt_pqueue/module-type-S/index.html create mode 100644 dev/lwt/Lwt_preemptive/index.html create mode 100644 dev/lwt/Lwt_process/class-process/index.html create mode 100644 dev/lwt/Lwt_process/class-process_full/index.html create mode 100644 dev/lwt/Lwt_process/class-process_in/index.html create mode 100644 dev/lwt/Lwt_process/class-process_none/index.html create mode 100644 dev/lwt/Lwt_process/class-process_out/index.html create mode 100644 dev/lwt/Lwt_process/index.html create mode 100644 dev/lwt/Lwt_result/Infix/index.html create mode 100644 dev/lwt/Lwt_result/Let_syntax/Let_syntax/Open_on_rhs/index.html create mode 100644 dev/lwt/Lwt_result/Let_syntax/Let_syntax/index.html create mode 100644 dev/lwt/Lwt_result/Let_syntax/index.html create mode 100644 dev/lwt/Lwt_result/Syntax/index.html create mode 100644 dev/lwt/Lwt_result/index.html create mode 100644 dev/lwt/Lwt_seq/index.html create mode 100644 dev/lwt/Lwt_sequence/index.html create mode 100644 dev/lwt/Lwt_stream/class-type-bounded_push/index.html create mode 100644 dev/lwt/Lwt_stream/index.html create mode 100644 dev/lwt/Lwt_switch/index.html create mode 100644 dev/lwt/Lwt_sys/index.html create mode 100644 dev/lwt/Lwt_throttle/Make/argument-1-H/index.html create mode 100644 dev/lwt/Lwt_throttle/Make/index.html create mode 100644 dev/lwt/Lwt_throttle/index.html create mode 100644 dev/lwt/Lwt_throttle/module-type-S/index.html create mode 100644 dev/lwt/Lwt_timeout/index.html create mode 100644 dev/lwt/Lwt_unix/IO_vectors/index.html create mode 100644 dev/lwt/Lwt_unix/LargeFile/index.html create mode 100644 dev/lwt/Lwt_unix/Versioned/index.html create mode 100644 dev/lwt/Lwt_unix/index.html create mode 100644 dev/lwt/_doc-dir/CHANGES create mode 100644 dev/lwt/_doc-dir/LICENSE.md create mode 100644 dev/lwt/_doc-dir/README.md create mode 100644 dev/lwt/_doc-dir/odoc-pages/index.mld create mode 100644 dev/lwt/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt/IO/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt/IO_in/class-type-t/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt/IO_in/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt/IO_out/class-type-t/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt/IO_out/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt/TCP_client/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt/TCP_server/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt__/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt__Base/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt__IO/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt__IO_in/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt__IO_out/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt__Tcp_client/index.html create mode 100644 dev/moonpool-lwt/Moonpool_lwt__Tcp_server/index.html create mode 100644 dev/moonpool-lwt/_doc-dir/CHANGES.md create mode 100644 dev/moonpool-lwt/_doc-dir/README.md create mode 100644 dev/moonpool-lwt/index.html diff --git a/dev/index.html b/dev/index.html index aaac8143..fbf4d185 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,2 +1,2 @@ -_opam

OCaml package documentation

Browse by name, by tag, the standard library and the OCaml manual (online, latest version).

Generated for /home/runner/work/moonpool/moonpool/_opam/lib

Packages by name

Packages by tag

\ No newline at end of file +_opam

OCaml package documentation

Browse by name, by tag, the standard library and the OCaml manual (online, latest version).

Generated for /home/runner/work/moonpool/moonpool/_opam/lib

Packages by name

Packages by tag

\ No newline at end of file diff --git a/dev/lwt/Lwt/Exception_filter/index.html b/dev/lwt/Lwt/Exception_filter/index.html new file mode 100644 index 00000000..6a4a4d20 --- /dev/null +++ b/dev/lwt/Lwt/Exception_filter/index.html @@ -0,0 +1,2 @@ + +Exception_filter (lwt.Lwt.Exception_filter)

Module Lwt.Exception_filter

type t

An Exception_filter.t is a value which indicates to Lwt what exceptions to catch and what exceptions to let bubble up all the way out of the main loop immediately.

val handle_all : t

handle_all is the default filter. With it the all the exceptions (including Out_of_memory and Stack_overflow) can be handled: caught and transformed into rejected promises.

val handle_all_except_runtime : t

handle_all_except_runtime is a filter which lets the OCaml runtime exceptions (Out_of_memory and Stack_overflow) go through all the Lwt abstractions and bubble all the way out of the call to Lwt_main.run.

Note that if you set this handler, then the runtime exceptions leave the Lwt internal state inconsistent. For this reason, you will not be able to call Lwt_main.run again after such an exception has escaped Lwt_main.run.

val set : t -> unit

set sets the given exception filter globally. You should call this function at most once during the start of your program, before the first call to Lwt_main.run.

diff --git a/dev/lwt/Lwt/Infix/Let_syntax/Open_on_rhs/index.html b/dev/lwt/Lwt/Infix/Let_syntax/Open_on_rhs/index.html new file mode 100644 index 00000000..89f8ca85 --- /dev/null +++ b/dev/lwt/Lwt/Infix/Let_syntax/Open_on_rhs/index.html @@ -0,0 +1,2 @@ + +Open_on_rhs (lwt.Lwt.Infix.Let_syntax.Open_on_rhs)

Module Let_syntax.Open_on_rhs

diff --git a/dev/lwt/Lwt/Infix/Let_syntax/index.html b/dev/lwt/Lwt/Infix/Let_syntax/index.html new file mode 100644 index 00000000..6d87cbf4 --- /dev/null +++ b/dev/lwt/Lwt/Infix/Let_syntax/index.html @@ -0,0 +1,2 @@ + +Let_syntax (lwt.Lwt.Infix.Let_syntax)

Module Infix.Let_syntax

This module provides support for ppx_let.

val return : 'a -> 'a t
val map : 'a t -> f:('a -> 'b) -> 'b t

See Lwt.map.

val bind : 'a t -> f:('a -> 'b t) -> 'b t
val both : 'a t -> 'b t -> ('a * 'b) t
module Open_on_rhs : sig ... end
diff --git a/dev/lwt/Lwt/Infix/index.html b/dev/lwt/Lwt/Infix/index.html new file mode 100644 index 00000000..df22eefa --- /dev/null +++ b/dev/lwt/Lwt/Infix/index.html @@ -0,0 +1,14 @@ + +Infix (lwt.Lwt.Infix)

Module Lwt.Infix

This module provides several infix operators for making programming with Lwt more convenient.

To use it, open Lwt.Infix.

Of the operators declared in this module, only >|= is recommended for new code. The only other commonly-used operator is >>=.

val (>>=) : 'a t -> ('a -> 'b t) -> 'b t

p >>= f is the same as Lwt.bind p f. It requires Lwt.Infix to be opened in scope:

open Lwt.Infix
+
+let () =
+  Lwt_main.run
+    (Lwt_io.(read_line stdin) >>= Lwt_io.printl)
+
+(* ocamlfind opt -linkpkg -thread -package lwt.unix code.ml && ./a.out *)

It is recommended to use the PPX let%lwt syntax instead. This operator is the next-best choice. It is frequently found while reading existing Lwt code.

val (>|=) : 'a t -> ('a -> 'b) -> 'b t

p >|= f is the same as Lwt.map f p. It requires Lwt.Infix to be opened in scope.

open Lwt.Infix
+
+let () =
+  Lwt_main.run
+    (Lwt_io.(read_line stdin) >|= ignore)
+
+(* ocamlfind opt -linkpkg -thread -package lwt.unix code.ml && ./a.out *)
val (<&>) : unit t -> unit t -> unit t

p1 <&> p2 is the same as Lwt.join [p1; p2]. It requires Lwt.Infix to be opened in scope.

Unlike with Lwt.bind and Lwt.map, there are no problems with explicit Lwt.join syntax, so using this operator is not recommended.

val (<?>) : 'a t -> 'a t -> 'a t

p1 <?> p2 is the same as Lwt.choose [p1; p2]. It requires Lwt.Infix to be opened in scope.

Unlike with Lwt.bind and Lwt.map, there are no problems with explicit Lwt.choose syntax, so using this operator is not recommended.

Furthermore, most users actually need Lwt.pick instead of Lwt.choose.

val (=<<) : ('a -> 'b t) -> 'a t -> 'b t

f =<< p is the same as Lwt.bind p f. It requires Lwt.Infix to be opened in scope.

This operator is obscure and its use is discouraged. It is the same as p >>= f.

val (=|<) : ('a -> 'b) -> 'a t -> 'b t

f =|< p is the same as Lwt.map f p. It requires Lwt.Infix to be opened in scope.

This operator is obscure and its use is discouraged. It is the same as p >|= f.

module Let_syntax : sig ... end

This module provides support for ppx_let.

diff --git a/dev/lwt/Lwt/Let_syntax/Let_syntax/Open_on_rhs/index.html b/dev/lwt/Lwt/Let_syntax/Let_syntax/Open_on_rhs/index.html new file mode 100644 index 00000000..c1cd1f12 --- /dev/null +++ b/dev/lwt/Lwt/Let_syntax/Let_syntax/Open_on_rhs/index.html @@ -0,0 +1,2 @@ + +Open_on_rhs (lwt.Lwt.Let_syntax.Let_syntax.Open_on_rhs)

Module Let_syntax.Open_on_rhs

diff --git a/dev/lwt/Lwt/Let_syntax/Let_syntax/index.html b/dev/lwt/Lwt/Let_syntax/Let_syntax/index.html new file mode 100644 index 00000000..d500224a --- /dev/null +++ b/dev/lwt/Lwt/Let_syntax/Let_syntax/index.html @@ -0,0 +1,2 @@ + +Let_syntax (lwt.Lwt.Let_syntax.Let_syntax)

Module Let_syntax.Let_syntax

val return : 'a -> 'a t
val map : 'a t -> f:('a -> 'b) -> 'b t

See Lwt.map.

val bind : 'a t -> f:('a -> 'b t) -> 'b t
val both : 'a t -> 'b t -> ('a * 'b) t
module Open_on_rhs : sig ... end
diff --git a/dev/lwt/Lwt/Let_syntax/index.html b/dev/lwt/Lwt/Let_syntax/index.html new file mode 100644 index 00000000..7bff6901 --- /dev/null +++ b/dev/lwt/Lwt/Let_syntax/index.html @@ -0,0 +1,2 @@ + +Let_syntax (lwt.Lwt.Let_syntax)

Module Lwt.Let_syntax

module Let_syntax : sig ... end
diff --git a/dev/lwt/Lwt/Syntax/index.html b/dev/lwt/Lwt/Syntax/index.html new file mode 100644 index 00000000..1e7afae7 --- /dev/null +++ b/dev/lwt/Lwt/Syntax/index.html @@ -0,0 +1,2 @@ + +Syntax (lwt.Lwt.Syntax)

Module Lwt.Syntax

Let syntax

Monadic syntax

val let* : 'a t -> ('a -> 'b t) -> 'b t

Syntax for bind.

val and* : 'a t -> 'b t -> ('a * 'b) t

Syntax for both.

Applicative syntax

val let+ : 'a t -> ('a -> 'b) -> 'b t

Syntax for map.

val and+ : 'a t -> 'b t -> ('a * 'b) t

Syntax for both.

diff --git a/dev/lwt/Lwt/index.html b/dev/lwt/Lwt/index.html new file mode 100644 index 00000000..c3795c40 --- /dev/null +++ b/dev/lwt/Lwt/index.html @@ -0,0 +1,356 @@ + +Lwt (lwt.Lwt)

Module Lwt

Asynchronous programming with promises.

A promise is a placeholder for a single value which might take a long time to compute. Speaking roughly, a promise is a ref that can be filled in later. To make that precise, here is how promises differ from refs:

So, promises are optional, write-once references, and when they don't yet have a value, they store a list of callbacks that are waiting for the value.

The waiting callbacks make promises a natural data type for asynchronous programming. For example, you can ask Lwt to read a file. Lwt immediately returns you only a promise for the data.

You can neglect this promise for a while. You can do some other computation, request more I/O, etc. At some point, you might decide to attach a callback to the read promise, maybe several callbacks.

In the meantime, the read operation is running in the background. Once it finishes, Lwt resolves the read promise by putting the data into it. Lwt then runs the callbacks you attached.

One of those might take the data, and ask Lwt to write it to STDOUT. Lwt gives you a promise for that, too, and the process repeats.

Lwt has a small amount of syntactic sugar to make this look as natural as possible:

let () =
+  Lwt_main.run begin
+    let%lwt data = Lwt_io.(read_line stdin) in
+    let%lwt () = Lwt_io.printl data in
+    Lwt.return ()
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix echo.ml && ./a.out *)

This is all explained in the next sections:

After that is the reference proper, which goes into painful levels of detail on every single type and value in this module, Lwt. Please be safe, and read only what you need from it :)

Happy asynchronous programming!

Quick start

All of Lwt is variations on:

Tutorial

Let's read from STDIN. The first version is written using ordinary values from the OCaml standard library. This makes the program block until the user enters a line:

let () =
+  let line : string = read_line () in
+  print_endline "Now unblocked!";
+  ignore line
+
+(* ocamlfind opt -linkpkg code.ml && ./a.out *)

If we use a promise instead, execution continues immediately:

let () =
+  let line_promise : string Lwt.t =
+    Lwt_io.(read_line stdin) in
+  print_endline "Execution just continues...";
+  ignore line_promise
+
+(* ocamlfind opt -linkpkg -thread -package lwt.unix code.ml && ./a.out *)

Indeed, this program is a little too asynchronous – it exits right away! Let's force it to wait for line_promise at the end by calling Lwt_main.run:

let () =
+  let line_promise : string Lwt.t =
+    Lwt_io.(read_line stdin) in
+  print_endline "Execution just continues...";
+
+  let line : string =
+    Lwt_main.run line_promise in
+  ignore line
+
+(* ocamlfind opt -linkpkg -thread -package lwt.unix code.ml && ./a.out *)

Lwt_main.run should only be called once, on one promise, at the top level of your program. Most of the time, waiting for promises is done using let%lwt. That is the recommended syntactic sugar for Lwt.bind, and is pronounced β€œbind”:

let () =
+  let p : unit Lwt.t =
+    let%lwt line_1 = Lwt_io.(read_line stdin) in
+    let%lwt line_2 = Lwt_io.(read_line stdin) in
+    Lwt_io.printf "%s and %s\n" line_1 line_2
+  in
+
+  Lwt_main.run p
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

The way that works is everything in scope after the β€œin” in β€œlet%lwt x = ... in ...” goes into a callback, and β€œx” is that callback's argument. So, we could have been very explicit, and written the code like this:

let () =
+  let p : unit Lwt.t =
+    let line_1_promise : string Lwt.t = Lwt_io.(read_line stdin) in
+    Lwt.bind line_1_promise (fun (line_1 : string) ->
+
+      let line_2_promise : string Lwt.t = Lwt_io.(read_line stdin) in
+      Lwt.bind line_2_promise (fun (line_2 : string) ->
+
+        Lwt_io.printf "%s and %s\n" line_1 line_2))
+  in
+
+  Lwt_main.run p
+
+(* ocamlfind opt -linkpkg -thread -package lwt.unix code.ml && ./a.out *)

But, as you can see, this is verbose, and the indentation gets a bit crazy. So, we will always use let%lwt.

The code above reads two lines in sequence, because we ask Lwt to wait for line_1, before calling the second Lwt_io.read_line in the callback, to start the second I/O.

We could also run I/O concurrently. All we have to do is not start the second I/O in a callback of the first. Because it doesn't make sense to read two lines from STDIN concurrently, let's start two waits instead:

let () =
+  Lwt_main.run begin
+    let three_seconds : unit Lwt.t = Lwt_unix.sleep 3. in
+    let five_seconds : unit Lwt.t = Lwt_unix.sleep 5. in
+    let%lwt () = three_seconds in
+    let%lwt () = Lwt_io.printl "3 seconds passed" in
+    let%lwt () = five_seconds in
+    Lwt_io.printl "Only 2 more seconds passed"
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

This program takes about five seconds to run. We are still new to let%lwt, so let's desugar it:

let () =
+  Lwt_main.run begin
+    let three_seconds : unit Lwt.t = Lwt_unix.sleep 3. in
+    let five_seconds : unit Lwt.t = Lwt_unix.sleep 5. in
+
+    (* Both waits have already been started at this point! *)
+
+    Lwt.bind three_seconds (fun () ->
+      (* This is 3 seconds later. *)
+      Lwt.bind (Lwt_io.printl "3 seconds passed") (fun () ->
+        Lwt.bind five_seconds (fun () ->
+          (* Only 2 seconds were left in the 5-second wait, so
+              this callback runs 2 seconds after the first callback. *)
+          Lwt_io.printl "Only 2 more seconds passed")))
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt.unix code.ml && ./a.out *)

And that's it! Concurrency in Lwt is simply a matter of whether you start an operation in the callback of another one or not. As a convenience, Lwt provides a few helpers for common concurrency patterns.

Execution model

It's important to understand that promises are a pure-OCaml data type. They don't do any fancy scheduling or I/O. They are just lists of callbacks (if pending), or containers for one value (if resolved).

The interesting function is Lwt_main.run. It's a wrapper around select(2), epoll(7), kqueue(2), or whatever asynchronous I/O API your system provides. On browsers, the work of Lwt_main.run is done by the surrounding JavaScript engine, so you don't call Lwt_main.run from inside your program. But the execution model is still the same, and the description below applies!

To avoid writing out β€œunderlying asynchronous I/O API,” we'll assume, in this section, that the API is select(2). That's just for the sake of abbreviation. It doesn't actually matter, for most purposes, what the underlying I/O API is.

Let's use the program from the tutorial that reads two lines as an example. Here it is, again, in its desugared form:

let () =
+  let p : unit Lwt.t =
+    let line_1_promise : string Lwt.t = Lwt_io.(read_line stdin) in
+    Lwt.bind line_1_promise (fun (line_1 : string) ->
+
+      let line_2_promise : string Lwt.t = Lwt_io.(read_line stdin) in
+      Lwt.bind line_2_promise (fun (line_2 : string) ->
+
+        Lwt_io.printf "%s and %s\n" line_1 line_2))
+  in
+
+  Lwt_main.run p
+
+(* ocamlfind opt -linkpkg -thread -package lwt.unix code.ml && ./a.out *)

Lwt_main.run is your program's main I/O loop. You pass it a single promise, and it:

  1. Uses select(2) to put your process to sleep until the next I/O completes.
  2. That next I/O happens to be the one that reads line_1. Lwt_main.run knows that I/O is supposed to resolve line_1_promise, so it puts line_1 into the promise and resolves it.
  3. Resolving is an ordinary OCaml operation. It causes all the callbacks of line_1_promise to run, one after another. Each callback is also ordinary OCaml code. In our case, there is only one callback, but in general, there might be several, and they might also resolve additional promises. So, promise resolution triggers a β€œcascade” of callbacks. Eventually, however, we should run out of callbacks, and control will return to Lwt_main.run.
  4. In our example, our one callback registers a second I/O with Lwt_main.run – the one that will read line_2. There are no callbacks left to run after that, so control returns to Lwt_main.run.
  5. Lwt_main.run goes back to sleep again by calling select(2), now waiting for the second I/O that we just registered. The loop repeats itself from step 1.

This has two major implications, one good and one bad. Let's start with the bad one.

(1) If one of your callbacks enters an infinite loop, calls an Lwt-unfriendly blocking I/O, or just runs for a really long time, it won't return control to Lwt_main.run anytime soon. That means Lwt_main.run won't get a chance to resolve any other Lwt I/O promises, even if the underlying I/O operations complete.

In case your callback is just using the CPU for a really long time, you can insert a few calls to Lwt.pause into it, and resume your computation in callbacks of pause. This is basically the same as Lwt_unix.sleep 0. – it's a promise that will be resolved by Lwt_main.run after any other I/O resolutions that are already in its queue.

(2) The good implication is that all your callbacks run in a single thread. This means that in most situations, you don't have to worry about locks, synchronization, etc. Anything that is in the same callback is guaranteed to run without interruption. Lwt programs are often much easier to write and refactor, than equivalent programs written with threads – but both are concurrent!

Guide to the rest of Lwt

This module Lwt is the pure-OCaml definition of promises and callback-calling. It has a few extras on top of what's described above:

The next layer above module Lwt is the pure-OCaml Lwt β€œcore” library, which provides some promise-friendly patterns, like streams and mvars. This consists of the modules Lwt_list, Lwt_stream, Lwt_result, Lwt_mutex, Lwt_condition, Lwt_mvar, Lwt_pool, and Lwt_switch.

Above that is the Lwt Unix binding, where I/O begins. This includes the module Lwt_main, including the all-important Lwt_main.run. The rest of the Unix binding consists of functions, each one of which...

The functions are grouped into modules:

Warning! Introductory material ends and detailed reference begins!

Fundamentals

Promises

type +'a t

Promises for values of type 'a.

A promise is a memory cell that is always in one of three states:

  • fulfilled, and containing one value of type 'a,
  • rejected, and containing one exception, or
  • pending, in which case it may become fulfilled or rejected later.

A resolved promise is one that is either fulfilled or rejected, i.e. not pending. Once a promise is resolved, its content cannot change. So, promises are write-once references. The only possible state changes are (1) from pending to fulfilled and (2) from pending to rejected.

Promises are typically β€œread” by attaching callbacks to them. The most basic functions for that are Lwt.bind, which attaches a callback that is called when a promise becomes fulfilled, and Lwt.catch, for rejection.

Promise variables of this type, 'a Lwt.t, are actually read-only in Lwt. Separate resolvers of type 'a Lwt.u are used to write to them. Promises and their resolvers are created together by calling Lwt.wait. There is one exception to this: most promises can be canceled by calling Lwt.cancel, without going through a resolver.

type -'a u

Resolvers for promises of type 'a Lwt.t.

Each resolver can be thought of as the write end of one promise. It can be passed to Lwt.wakeup_later, Lwt.wakeup_later_exn, or Lwt.wakeup_later_result to resolve that promise.

val wait : unit -> 'a t * 'a u

Creates a new pending promise, paired with its resolver.

It is rare to use this function directly. Many helpers in Lwt, and Lwt-aware libraries, call it internally, and return only the promise. You then chain the promises together using Lwt.bind.

However, it is important to understand Lwt.wait as the fundamental promise β€œconstructor.” All other functions that evaluate to a promise can be, or are, eventually implemented in terms of it.

Resolving

val wakeup_later : 'a u -> 'a -> unit

Lwt.wakeup_later r v fulfills, with value v, the pending promise associated with resolver r. This triggers callbacks attached to the promise.

If the promise is not pending, Lwt.wakeup_later raises Stdlib.Invalid_argument, unless the promise is canceled. If the promise is canceled, Lwt.wakeup_later has no effect.

If your program has multiple threads, it is important to make sure that Lwt.wakeup_later (and any similar function) is only called from the main thread. Lwt.wakeup_later can trigger callbacks attached to promises by the program, and these assume they are running in the main thread. If you need to communicate from a worker thread to the main thread running Lwt, see Lwt_preemptive or Lwt_unix.send_notification.

val wakeup_later_exn : _ u -> exn -> unit

Lwt.wakeup_later_exn r exn is like Lwt.wakeup_later, except, if the associated promise is pending, it is rejected with exn.

val return : 'a -> 'a t

Lwt.return v creates a new promise that is already fulfilled with value v.

This is needed to satisfy the type system in some cases. For example, in a match expression where one case evaluates to a promise, the other cases have to evaluate to promises as well:

match need_input with
+| true -> Lwt_io.(read_line stdin)   (* Has type string Lwt.t... *)
+| false -> Lwt.return ""             (* ...so wrap empty string in a promise. *)

Another typical usage is in let%lwt. The expression after the β€œin” has to evaluate to a promise. So, if you compute an ordinary value instead, you have to wrap it:

let%lwt line = Lwt_io.(read_line stdin) in
+Lwt.return (line ^ ".")
val fail : exn -> _ t

Lwt.fail exn is like Lwt.return, except the new promise that is already rejected with exn.

Whenever possible, it is recommended to use raise exn instead, as raise captures a backtrace, while Lwt.fail does not. If you call raise exn in a callback that is expected by Lwt to return a promise, Lwt will automatically wrap exn in a rejected promise, but the backtrace will have been recorded by the OCaml runtime.

For example, bind's second argument is a callback which returns a promise. And so it is recommended to use raise in the body of that callback. This applies to the aliases of bind as well: ( >>= ) and ( let* ).

Use Lwt.fail only when you specifically want to create a rejected promise, to pass to another function, or store in a data structure.

Callbacks

val bind : 'a t -> ('a -> 'b t) -> 'b t

Lwt.bind p_1 f makes it so that f will run when p_1 is fulfilled.

When p_1 is fulfilled with value v_1, the callback f is called with that same value v_1. Eventually, after perhaps starting some I/O or other computation, f returns promise p_2.

Lwt.bind itself returns immediately. It only attaches the callback f to p_1 – it does not wait for p_2. What Lwt.bind returns is yet a third promise, p_3. Roughly speaking, fulfillment of p_3 represents both p_1 and p_2 becoming fulfilled, one after the other.

A minimal example of this is an echo program:

let () =
+  let p_3 =
+    Lwt.bind
+      Lwt_io.(read_line stdin)
+      (fun line -> Lwt_io.printl line)
+  in
+  Lwt_main.run p_3
+
+(* ocamlfind opt -linkpkg -thread -package lwt.unix code.ml && ./a.out *)

Rejection of p_1 and p_2, and raising an exception in f, are all forwarded to rejection of p_3.

Precise behavior

Lwt.bind returns a promise p_3 immediately. p_3 starts out pending, and is resolved as follows:

  • The first condition to wait for is that p_1 becomes resolved. It does not matter whether p_1 is already resolved when Lwt.bind is called, or becomes resolved later – the rest of the behavior is the same.
  • If and when p_1 becomes resolved, it will, by definition, be either fulfilled or rejected.
  • If p_1 is rejected, p_3 is rejected with the same exception.
  • If p_1 is fulfilled, with value v, f is applied to v.
  • f may finish by returning the promise p_2, or raising an exception.
  • If f raises an exception, p_3 is rejected with that exception.
  • Finally, the remaining case is when f returns p_2. From that point on, p_3 is effectively made into a reference to p_2. This means they have the same state, undergo the same state changes, and performing any operation on one is equivalent to performing it on the other.

Syntactic sugar

Lwt.bind is almost never written directly, because sequences of Lwt.bind result in growing indentation and many parentheses:

let () =
+  Lwt_main.run begin
+    Lwt.bind Lwt_io.(read_line stdin) (fun line ->
+      Lwt.bind (Lwt_unix.sleep 1.) (fun () ->
+        Lwt_io.printf "One second ago, you entered %s\n" line))
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt.unix code.ml && ./a.out *)

The recommended way to write Lwt.bind is using the let%lwt syntactic sugar:

let () =
+  Lwt_main.run begin
+    let%lwt line = Lwt_io.(read_line stdin) in
+    let%lwt () = Lwt_unix.sleep 1. in
+    Lwt_io.printf "One second ago, you entered %s\n" line
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

This uses the Lwt PPX (preprocessor). Note that we had to add package lwt_ppx to the command line for building this program. We will do that throughout this manual.

Another way to write Lwt.bind, that you may encounter while reading code, is with the >>= operator:

open Lwt.Infix
+
+let () =
+  Lwt_main.run begin
+    Lwt_io.(read_line stdin) >>= fun line ->
+    Lwt_unix.sleep 1. >>= fun () ->
+    Lwt_io.printf "One second ago, you entered %s\n" line
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt.unix code.ml && ./a.out *)

The >>= operator comes from the module Lwt.Infix, which is why we opened it at the beginning of the program.

See also Lwt.map.

Rejection

val reraise : exn -> 'a

reraise e raises the exception e. Unlike raise e, reraise e preserves the existing exception backtrace and even adds a "Re-raised at" entry with the call location.

This function is intended to be used in the exception handlers of Lwt.catch and Lwt.try_bind.

It is also used in the code produced by Lwt_ppx.

val catch : (unit -> 'a t) -> (exn -> 'a t) -> 'a t

Lwt.catch f h applies f (), which returns a promise, and then makes it so that h (β€œhandler”) will run when that promise is rejected.

let () =
+  Lwt_main.run begin
+    Lwt.catch
+      (fun () -> raise Exit)
+      (function
+      | Exit -> Lwt_io.printl "Got Stdlib.Exit"
+      | exn -> Lwt.reraise exn)
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt.unix code.ml && ./a.out *)

Despite the above code, the recommended way to write Lwt.catch is using the try%lwt syntactic sugar from the PPX. Here is an equivalent example:

let () =
+  Lwt_main.run begin
+    try%lwt raise Exit
+    with Exit -> Lwt_io.printl "Got Stdlb.Exit"
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

A particular advantage of the PPX syntax is that it is not necessary to artificially insert a catch-all exn -> reraise exn case. Like in the core language's try expression, the catch-all case is implied in try%lwt.

Lwt.catch is a counterpart to Lwt.bind – Lwt.bind is for fulfillment, and Lwt.catch is for rejection.

As with Lwt.bind, three promises are involved:

  • p_1, the promise returned from applying f ().
  • p_2, the promise returned from applying h exn.
  • p_3, the promise returned by Lwt.catch itself.

The remainder is (1) a precise description of how p_3 is resolved, and (2) a warning about accidentally using ordinary try for exception handling in asynchronous code.

(1) Lwt.catch first applies f (). It then returns p_3 immediately. p_3 starts out pending. It is resolved as follows:

  • If f () returned a promise p_1, and p_1 becomes fulfilled, p_3 is fulfilled with the same value.
  • p_1 can instead become rejected. There is one other possibility: f () itself raised an exception, instead of returning a promise. The behavior of Lwt.catch is the same whether f () raised an exception, or returned a promise that is later rejected with an exception. Let's call the exception exn.
  • h exn is applied.
  • h exn may return a promise, or might itself raise an exception. The first case is the interesting one, but the exception case is simple, so we cover the exception case first.
  • If h exn raises another exception exn', p_3 is rejected with exn'.
  • If h exn instead returns the promise p_2, p_3 is effectively made into a reference to p_2. This means p_3 and p_2 have the same state, undergo the same state changes, and performing any operation one is equivalent to performing it on the other.
val finalize : (unit -> 'a t) -> (unit -> unit t) -> 'a t

Lwt.finalize f c applies f (), which returns a promise, and then makes it so c (β€œcleanup”) will run when that promise is resolved.

In other words, c runs no matter whether promise f () is fulfilled or rejected. As the names suggest, Lwt.finalize corresponds to the finally construct found in many programming languages, and c is typically used for cleaning up resources:

let () =
+  Lwt_main.run begin
+    let%lwt file = Lwt_io.(open_file ~mode:Input "code.ml") in
+    Lwt.finalize
+      (fun () ->
+        let%lwt content = Lwt_io.read file in
+        Lwt_io.print content)
+      (fun () ->
+        Lwt_io.close file)
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

As with Lwt.bind and Lwt.catch, there is a syntactic sugar for Lwt.finalize, though it is not as often used:

let () =
+  Lwt_main.run begin
+    let%lwt file = Lwt_io.(open_file ~mode:Input "code.ml") in
+    begin
+      let%lwt content = Lwt_io.read file in
+      Lwt_io.print content
+    end
+    [%lwt.finally
+      Lwt_io.close file]
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

Also as with Lwt.bind and Lwt.catch, three promises are involved:

  • p_1, the promise returned from applying f ().
  • p_2, the promise returned from applying c ().
  • p_3, the promise returned by Lwt.finalize itself.

p_3 is returned immediately. It starts out pending, and is resolved as follows:

  • f () is applied. If it finishes, it will either return a promise p_1, or raise an exception.
  • If f () raises an exception, p_1 is created artificially as a promise rejected with that exception. So, no matter how f () finishes, there is a promise p_1 representing the outcome.
  • After p_1 is resolved (fulfilled or rejected), c () is applied. This is meant to be the cleanup code.
  • If c () finishes, it will also either return a promise, p_2, or raise an exception.
  • If c () raises an exception, p_2 is created artificially as a promise rejected with that exception. Again, no matter how c () finishes, there is a promise p_2 representing the outcome of cleanup.
  • If p_2 is fulfilled, p_3 is resolved the same way p_1 had been resolved. In other words, p_1 is forwarded to p_3 when cleanup is successful.
  • If p_2 is rejected, p_3 is rejected with the same exception. In other words, p_2 is forwarded to p_3 when cleanup is unsuccessful. Note this means that if both the protected code and the cleanup fail, the cleanup exception has precedence.
val try_bind : (unit -> 'a t) -> ('a -> 'b t) -> (exn -> 'b t) -> 'b t

Lwt.try_bind f g h applies f (), and then makes it so that:

Lwt.try_bind is a generalized Lwt.finalize. The difference is that Lwt.try_bind runs different callbacks depending on how f () is resolved. This has two main implications:

  • The cleanup functions g and h each β€œknow” whether f () was fulfilled or rejected.
  • The cleanup functions g and h are passed the value f () was fulfilled with, and, respectively, the exception f () was rejected with.

As with Lwt.catch, it is recommended to use reraise in the catch-all case of the exception handler:

let () =
+  Lwt_main.run begin
+    Lwt.try_bind
+      (fun () -> raise Exit)
+      (fun () -> Lwt_io.printl "Got Success")
+      (function
+      | Exit -> Lwt_io.printl "Got Stdlib.Exit"
+      | exn -> Lwt.reraise exn)
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt.unix code.ml && ./a.out *)

The rest is a detailed description of the promises involved.

As with Lwt.finalize and the several preceding functions, three promises are involved.

  • p_1 is the promise returned from applying f ().
  • p_2 is the promise returned from applying h or g, depending on which one is chosen.
  • p_3 is the promise returned by Lwt.try_bind itself.

Lwt.try_bind returns p_3 immediately. p_3 starts out pending, and is resolved as follows:

  • f () is applied. If it finishes, it either returns p_1, or raises an exception.
  • If f () raises an exception, p_1 is created artificially as a promise rejected with that exception. So, no matter how f () finishes, there is a promise p_1 representing the outcome.
  • If p_1 is fulfilled, g is applied to the value p_1 is fulfilled with.
  • If p_1 is rejected, h is applied to the exception p_1 is rejected with.
  • So, in either case, a callback is applied. The rest of the procedure is the same no matter which callback was chosen, so we will refer to it as β€œthe callback.”
  • If the callback finishes, it either returns p_2, or raises an exception.
  • If the callback raises an exception, p_3 is rejected with that exception.
  • If the callback returns p_2, p_3 is effectively made into an reference to p_2. They have the same state, including any state changes, and performing any operation on one is equivalent to performing it on the other.
val dont_wait : (unit -> unit t) -> (exn -> unit) -> unit

Lwt.dont_wait f handler applies f (), which returns a promise, and then makes it so that if the promise is rejected, the exception is passed to handler.

In addition, if f () raises an exception, it is also passed to handler.

As the name implies, dont_wait (fun () -> <e>) handler is a way to evaluate the expression <e> (which typically has asynchronous side-effects) without waiting for the resolution of the promise <e> evaluates to.

dont_wait is meant as an alternative to async with a local, explicit, predictable exception handler.

Note that dont_wait f h causes f () to be evaluated immediately. Consequently, the non-yielding/non-pausing prefix of the body of f is evaluated immediately.

val async : (unit -> unit t) -> unit

Lwt.async f applies f (), which returns a promise, and then makes it so that if the promise is rejected, the exception is passed to !Lwt.async_exception_hook.

In addition, if f () raises an exception, it is also passed to !Lwt.async_exception_hook.

!Lwt.async_exception_hook typically prints an error message and terminates the program. If you need a similar behaviour with a different exception handler, you can use Lwt.dont_wait.

Lwt.async is misleadingly named. Itself, it has nothing to do with asynchronous execution. It's actually a safety function for making Lwt programs more debuggable.

For example, take this program, which prints messages in a loop, while waiting for one line of user input:

let () =
+  let rec show_nag () : _ Lwt.t =
+    let%lwt () = Lwt_io.printl "Please enter a line" in
+    let%lwt () = Lwt_unix.sleep 1. in
+    show_nag ()
+  in
+  ignore (show_nag ());     (* Bad – see note for (1)! *)
+
+  Lwt_main.run begin
+    let%lwt line = Lwt_io.(read_line stdin) in
+    Lwt_io.printl line
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

If one of the I/O operations in show_nag were to fail, the promise representing the whole loop would get rejected. However, since we are ignoring that promise at (1), we never find out about the rejection. If this failure and resulting rejection represents a bug in the program, we have a harder time finding out about the bug.

A safer version differs only in using Lwt.async instead of Stdlib.ignore:

let () =
+  let rec show_nag () : _ Lwt.t =
+    let%lwt () = Lwt_io.printl "Please enter a line" in
+    let%lwt () = Lwt_unix.sleep 1. in
+    show_nag ()
+  in
+  Lwt.async (fun () -> show_nag ());
+
+  Lwt_main.run begin
+    let%lwt line = Lwt_io.(read_line stdin) in
+    Lwt_io.printl line
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

In this version, if I/O in show_nag fails with an exception, the exception is printed by Lwt.async, and then the program exits.

The general rule for when to use Lwt.async is:

  • Promises which are not passed to Lwt.bind, Lwt.catch, Lwt.join, etc., are top-level promises.
  • One top-level promise is passed to Lwt_main.run, as can be seen in most examples in this manual.
  • Every other top-level promise should be wrapped in Lwt.async.
val async_exception_hook : (exn -> unit) ref

Reference to a function, to be called on an "unhandled" exception.

This reference is used by Lwt.async, Lwt.on_cancel, Lwt.on_success, Lwt.on_failure, Lwt.on_termination, Lwt.on_any, Lwt_react.of_stream, and the deprecated Lwt.ignore_result.

The initial, default implementation prints the exception, then terminates the process with non-zero exit status, as if the exception had reached the top level of the program:

let () = Lwt.async (fun () -> raise Exit)
+
+(* ocamlfind opt -linkpkg -package lwt code.ml && ./a.out *)

produces in the output:

Fatal error: exception Stdlib.Exit

If you are writing an application, you are welcome to reassign the reference, and replace the function with something more appropriate for your needs.

If you are writing a library, you should leave this reference alone. Its behavior should be determined by the application.

Concurrency

Multiple wait

val both : 'a t -> 'b t -> ('a * 'b) t

Lwt.both p_1 p_2 returns a promise that is pending until both promises p_1 and p_2 become resolved.

let () =
+  let p_1 =
+    let%lwt () = Lwt_unix.sleep 3. in
+    Lwt_io.printl "Three seconds elapsed"
+  in
+
+  let p_2 =
+    let%lwt () = Lwt_unix.sleep 5. in
+    Lwt_io.printl "Five seconds elapsed"
+  in
+
+  let p_3 = Lwt.both p_1 p_2 in
+  Lwt_main.run p_3
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

If both p_1 and p_2 become fulfilled, Lwt.both p_1 p_2 is also fulfilled, with the pair of their final values. Otherwise, if at least one of the two promises becomes rejected, Lwt.both p_1 p_2 is rejected with the same exception as one such promise, chosen arbitrarily. Note that this occurs only after both promises are resolved, not immediately when the first promise is rejected.

  • since 4.2.0
val join : unit t list -> unit t

Lwt.join ps returns a promise that is pending until all promises in the list ps become resolved.

let () =
+  let p_1 =
+    let%lwt () = Lwt_unix.sleep 3. in
+    Lwt_io.printl "Three seconds elapsed"
+  in
+
+  let p_2 =
+    let%lwt () = Lwt_unix.sleep 5. in
+    Lwt_io.printl "Five seconds elapsed"
+  in
+
+  let p_3 = Lwt.join [p_1; p_2] in
+  Lwt_main.run p_3
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

If all of the promises in ps become fulfilled, Lwt.join ps is also fulfilled. Otherwise, if at least one promise in ps becomes rejected, Lwt.join ps is rejected with the same exception as one such promise, chosen arbitrarily. Note that this occurs only after all the promises are resolved, not immediately when the first promise is rejected.

val all : 'a t list -> 'a list t

Lwt.all ps is like Lwt.join ps: it waits for all promises in the list ps to become resolved.

It then resolves the returned promise with the list of all resulting values.

Note that if any of the promises in ps is rejected, the returned promise is also rejected. This means that none of the values will be available, even if some of the promises in ps were already resolved when one of them is rejected. For more fine-grained handling of rejection, structure the program with Lwt_stream or Lwt_list, handle rejections explicitly, or use Lwt.join and collect values manually.

  • since 5.1.0

Racing

val pick : 'a t list -> 'a t

Lwt.pick ps returns a promise that is pending until one promise in the list ps becomes resolved.

When at least one promise in ps is resolved, Lwt.pick tries to cancel all other promises that are still pending, using Lwt.cancel.

let () =
+  let echo =
+    let%lwt line = Lwt_io.(read_line stdin) in
+    Lwt_io.printl line
+  in
+
+  let timeout = Lwt_unix.sleep 5. in
+
+  Lwt_main.run (Lwt.pick [echo; timeout])
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

If the first promise in ps to become resolved is fulfilled, the result promise p is also fulfilled, with the same value. Likewise, if the first promise in ps to become resolved is rejected, p is rejected with the same exception.

If ps has no promises (if it is the empty list), Lwt.pick ps raises Stdlib.Invalid_argument _.

It's possible for multiple promises in ps to become resolved simultaneously. This happens most often when some promises ps are already resolved at the time Lwt.pick is called.

In that case, if at least one of the promises is rejected, the result promise p is rejected with the same exception as one such promise, chosen arbitrarily. If all promises are fulfilled, p is fulfilled with the value of one of the promises, also chosen arbitrarily.

The remaining functions in this section are variations on Lwt.pick.

val choose : 'a t list -> 'a t

Lwt.choose ps is the same as Lwt.pick ps, except that it does not try to cancel pending promises in ps.

val npick : 'a t list -> 'a list t

Lwt.npick ps is similar to Lwt.pick ps, the difference being that when multiple promises in ps are fulfilled simultaneously (and none are rejected), the result promise is fulfilled with the list of values the promises were fulfilled with.

When at least one promise is rejected, Lwt.npick still rejects the result promise with the same exception.

val nchoose : 'a t list -> 'a list t

Lwt.nchoose ps is the same as Lwt.npick ps, except that it does not try to cancel pending promises in ps.

val nchoose_split : 'a t list -> ('a list * 'a t list) t

Lwt.nchoose_split ps is the same as Lwt.nchoose ps, except that when multiple promises in ps are fulfilled simultaneously (and none are rejected), the result promise is fulfilled with both the list of values of the fulfilled promises, and the list of promises that are still pending.

Cancellation

Note: cancelation has proved difficult to understand, explain, and maintain, so use of these functions is discouraged in new code. See ocsigen/lwt#283.

exception Canceled

Canceled promises are those rejected with this exception, Lwt.Canceled. See Lwt.cancel.

val task : unit -> 'a t * 'a u

Lwt.task is the same as Lwt.wait, except the resulting promise p is cancelable.

This is significant, because it means promises created by Lwt.task can be resolved (specifically, rejected) by canceling them directly, in addition to being resolved through their paired resolvers.

In contrast, promises returned by Lwt.wait can only be resolved through their resolvers.

val cancel : _ t -> unit

Lwt.cancel p attempts to cancel the pending promise p, without needing access to its resolver.

It is recommended to avoid Lwt.cancel, and handle cancelation by tracking the needed extra state explicitly within your library or application.

A canceled promise is one that has been rejected with exception Lwt.Canceled.

There are straightforward ways to make promises canceled. One could create a promise that starts out canceled, with Lwt.fail Lwt.Canceled. It's also possible to make a promise canceled through its resolver, by calling Lwt.wakeup_later_exn r Lwt.Canceled.

This function, Lwt.cancel, provides another method, which can cancel pending promises without going through their resolvers – it acts directly on promises.

Like any other promise rejection, the canceled state of a promise is propagated β€œforwards” by Lwt.bind, Lwt.join, etc., as described in the documentation of those functions.

Cancellation is a separate phase, triggered only by Lwt.cancel, that searches backwards, strating from p, for promises to reject with Lwt.Canceled. Once those promises are found, they are canceled, and then ordinary, forwards rejection propagation takes over.

All of this will be made precise, but first let's have an example:

let () =
+  let p =
+    let%lwt () = Lwt_unix.sleep 5. in
+    Lwt_io.printl "Slept five seconds"
+  in
+
+  Lwt.cancel p;
+
+  Lwt_main.run p
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

At the time Lwt.cancel is called, p β€œdepends” on the sleep promise (the printl is not yet called, so its promise hasn't been created).

So, Lwt.cancel recursively tries to cancel the sleep promise. That is an example of the backwards search. The sleep promise is a pending promise that doesn't depend on anything, so backwards search stops at it. The state of the sleep promise is set to rejected with Lwt.Canceled.

Lwt.bind then propagates the rejection forwards to p, so p also becomes canceled.

Eventually, this rejection reaches Lwt_main.run, which raises the Lwt.Canceled as an ordinary exception. The sleep does not complete, and the printl is never started.

Promises, like the sleep promise above, that can be rejected by Lwt.cancel are cancelable. Most promises in Lwt are either cancelable, or depend on cancelable promises. The functions Lwt.wait and Lwt.no_cancel create promises that are not cancelable.

The rest is a detailed description of how the Lwt.cancel backwards search works.

  • If p is already resolved, Lwt.cancel does nothing.
  • If p was created by Lwt.wait or Lwt.no_cancel, Lwt.cancel does nothing.
  • If p was created by Lwt.task or Lwt.protected, Lwt.cancel rejects it with Lwt.Canceled. This rejection then propagates normally through any Lwt calls that depend on p. Most I/O promises are internally created by calling Lwt.task.
  • Suppose p_3 was returned by Lwt.bind, Lwt.map, Lwt.catch, Lwt.finalize, or Lwt.try_bind. Then, see those functions for the naming of the other promises involved. If p_3 is pending, then either p_1 is pending, or p_2 is pending. Lwt.cancel p_3 then tries recursively to cancel whichever of these two is still pending. If that succeeds, p_3 may be canceled later by the normal propagation of rejection.
  • Suppose p was returned by Lwt.join, Lwt.pick, or similar function, which was applied to the promise list ps. Lwt.cancel then recursively tries to cancel each promise in ps. If one of those cancellations succeeds, p may be canceled later by the normal propagation of rejection.
val on_cancel : _ t -> (unit -> unit) -> unit

Lwt.on_cancel p f makes it so that f will run when p becomes canceled.

Callbacks scheduled with on_cancel are guaranteed to run before any other callbacks that are triggered by rejection, such as those added by Lwt.catch.

Note that this does not interact directly with the cancellation mechanism, the backwards search described in Lwt.cancel. For example, manually rejecting a promise with Lwt.Canceled is sufficient to trigger f.

f should not raise exceptions. If it does, they are passed to !Lwt.async_exception_hook, which terminates the process by default.

val protected : 'a t -> 'a t

Lwt.protected p creates a cancelable promise p'. The original state of p' is the same as the state of p at the time of the call.

The state of p' can change in one of two ways: a. if p changes state (i.e., is resolved), then p' eventually changes state to match p's, and b. during cancellation, if the backwards search described in Lwt.cancel reaches p' then it changes state to rejected Canceled and the search stops.

As a consequence of the b. case, Lwt.cancel (protected p) does not cancel p.

The promise p can still be canceled either directly (through Lwt.cancel p) or being reached by the backwards cancellation search via another path. Lwt.protected only prevents cancellation of p through p'.

val no_cancel : 'a t -> 'a t

Lwt.no_cancel p creates a non-cancelable promise p'. The original state of p' is the same as p at the time of the call.

If the state of p changes, then the state of p' eventually changes too to match p's.

Note that even though p' is non-cancelable, it can still become canceled if p is canceled. Lwt.no_cancel only prevents cancellation of p and p' through p'.

val wrap_in_cancelable : 'a t -> 'a t

Lwt.wrap_in_cancelable p creates a cancelable promise p'. The original state of p' is the same as p.

The state of p' can change in one of two ways: a. if p changes state (i.e., is resolved), then p' eventually changes state to match p's, and b. during cancellation, if the backwards search described in Lwt.cancel reaches p' then it changes state to rejected Canceled and the search continues to p.

Cancellation tweaks

The primitives protected, no_cancel, and wrap_in_cancelable give you some level of control over the cancellation mechanism of Lwt. Note that promises passed as arguments to either of these three functions are unchanged. The functions return new promises with a specific cancellation behaviour.

The three behaviour of all three functions are summarised in the following table.

+----------------------------+--------------------+--------------------+
+|     setup - action         | cancel p           | cancel p'          |
++----------------------------+--------------------+--------------------+
+| p is cancelable            | p is canceled      | p is not canceled  |
+| p' = protected p           | p'  is canceled    | p' is canceled     |
++----------------------------+--------------------+--------------------+
+| p is not cancelable        | p is not canceled  | p is not canceled  |
+| p' = protected p           | p' is not canceled | p' is canceled     |
++----------------------------+--------------------+--------------------+
+| p is cancelable            | p is canceled      | p is not canceled  |
+| p' = no_cancel p           | p' is canceled     | p' is not canceled |
++----------------------------+--------------------+--------------------+
+| p is not cancelable        | p is not canceled  | p is not canceled  |
+| p' = no_cancel p           | p' is not canceled | p' is not canceled |
++----------------------------+--------------------+--------------------+
+| p is cancelable            | p is canceled      | p is canceled      |
+| p' = wrap_in_cancelable p  | p' is canceled     | p' is canceled     |
++----------------------------+--------------------+--------------------+
+| p is not cancelable        | p is not canceled  | p is not canceled  |
+| p' = wrap_in_cancelable p  | p' is not canceled | p' is canceled     |
++----------------------------+--------------------+--------------------+

Convenience

Callback helpers

val map : ('a -> 'b) -> 'a t -> 'b t

Lwt.map f p_1 is similar to Lwt.bind p_1 f, but f is not expected to return a promise.

This function is more convenient than Lwt.bind when f inherently does not return a promise. An example is Stdlib.int_of_string:

let read_int : unit -> int Lwt.t = fun () ->
+  Lwt.map
+    int_of_string
+    Lwt_io.(read_line stdin)
+
+let () =
+  Lwt_main.run begin
+    let%lwt number = read_int () in
+    Lwt_io.printf "%i\n" number
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

By comparison, the Lwt.bind version is more awkward:

let read_int : unit -> int Lwt.t = fun () ->
+  Lwt.bind
+    Lwt_io.(read_line stdin)
+    (fun line -> Lwt.return (int_of_string line))

As with Lwt.bind, sequences of calls to Lwt.map result in excessive indentation and parentheses. The recommended syntactic sugar for avoiding this is the >|= operator, which comes from module Lwt.Infix:

open Lwt.Infix
+
+let read_int : unit -> int Lwt.t = fun () ->
+  Lwt_io.(read_line stdin) >|= int_of_string

The detailed operation follows. For consistency with the promises in Lwt.bind, the two promises involved are named p_1 and p_3:

  • p_1 is the promise passed to Lwt.map.
  • p_3 is the promise returned by Lwt.map.

Lwt.map returns a promise p_3. p_3 starts out pending. It is resolved as follows:

  • p_1 may be, or become, resolved. In that case, by definition, it will become fulfilled or rejected. Fulfillment is the interesting case, but the behavior on rejection is simpler, so we focus on rejection first.
  • When p_1 becomes rejected, p_3 is rejected with the same exception.
  • When p_1 instead becomes fulfilled, call the value it is fulfilled with v.
  • f v is applied. If this finishes, it may either return another value, or raise an exception.
  • If f v returns another value v', p_3 is fulfilled with v'.
  • If f v raises exception exn, p_3 is rejected with exn.
val on_success : 'a t -> ('a -> unit) -> unit

Lwt.on_success p f makes it so that f will run when p is fulfilled.

It is similar to Lwt.bind, except no new promises are created. f is a plain, arbitrary function attached to p, to perform some side effect.

If f raises an exception, it is passed to !Lwt.async_exception_hook. By default, this will terminate the process.

val on_failure : _ t -> (exn -> unit) -> unit

Lwt.on_failure p f makes it so that f will run when p is rejected.

It is similar to Lwt.catch, except no new promises are created.

If f raises an exception, it is passed to !Lwt.async_exception_hook. By default, this will terminate the process.

val on_termination : _ t -> (unit -> unit) -> unit

Lwt.on_termination p f makes it so that f will run when p is resolved – that is, fulfilled or rejected.

It is similar to Lwt.finalize, except no new promises are created.

If f raises an exception, it is passed to !Lwt.async_exception_hook. By default, this will terminate the process.

val on_any : 'a t -> ('a -> unit) -> (exn -> unit) -> unit

Lwt.on_any p f g makes it so that:

It is similar to Lwt.try_bind, except no new promises are created.

If f or g raise an exception, the exception is passed to !Lwt.async_exception_hook. By default, this will terminate the process.

Infix operators

module Infix : sig ... end

This module provides several infix operators for making programming with Lwt more convenient.

module Let_syntax : sig ... end
module Syntax : sig ... end

Pre-allocated promises

val return_unit : unit t

Lwt.return_unit is defined as Lwt.return (), but this definition is evaluated only once, during initialization of module Lwt, at the beginning of your program.

This means the promise is allocated only once. By contrast, each time Lwt.return () is evaluated, it allocates a new promise.

It is recommended to use Lwt.return_unit only where you know the allocations caused by an instance of Lwt.return () are a performance bottleneck. Generally, the cost of I/O tends to dominate the cost of Lwt.return () anyway.

In future Lwt, we hope to perform this optimization, of using a single, pre-allocated promise, automatically, wherever Lwt.return () is written.

val return_none : _ option t

Lwt.return_none is like Lwt.return_unit, but for Lwt.return None.

val return_nil : _ list t

Lwt.return_nil is like Lwt.return_unit, but for Lwt.return [].

val return_true : bool t

Lwt.return_true is like Lwt.return_unit, but for Lwt.return true.

val return_false : bool t

Lwt.return_false is like Lwt.return_unit, but for Lwt.return false.

Trivial promises

val return_some : 'a -> 'a option t

Counterpart to Lwt.return_none. However, unlike Lwt.return_none, this function performs no optimization. This is because it takes an argument, so it cannot be evaluated at initialization time, at which time the argument is not yet available.

val return_ok : 'a -> ('a, _) result t

Like Lwt.return_some, this function performs no optimization.

  • since Lwt 2.6.0
val return_error : 'e -> (_, 'e) result t

Like Lwt.return_some, this function performs no optimization.

  • since Lwt 2.6.0
val fail_with : string -> _ t

Lwt.fail_with s is an abbreviation for

Lwt.fail (Stdlib.Failure s)

In most cases, it is better to use failwith s from the standard library. See Lwt.fail for an explanation.

val fail_invalid_arg : string -> _ t

Lwt.invalid_arg s is an abbreviation for

Lwt.fail (Stdlib.Invalid_argument s)

In most cases, it is better to use invalid_arg s from the standard library. See Lwt.fail for an explanation.

Result type

A resolved promise of type 'a Lwt.t is either fulfilled with a value of type 'a, or rejected with an exception.

This corresponds to the cases of a ('a, exn)Stdlib.result: fulfilled corresponds to Ok of 'a, and rejected corresponds to Error of exn.

For Lwt programming with result where the Error constructor can carry arbitrary error types, see module Lwt_result.

val of_result : ('a, exn) result -> 'a t

Lwt.of_result r converts an r to a resolved promise.

  • If r is Ok v, Lwt.of_result r is Lwt.return v, i.e. a promise fulfilled with v.
  • If r is Error exn, Lwt.of_result r is Lwt.fail exn, i.e. a promise rejected with exn.
val wakeup_later_result : 'a u -> ('a, exn) result -> unit

Lwt.wakeup_later_result r result resolves the pending promise p associated to resolver r, according to result:

  • If result is Ok v, p is fulfilled with v.
  • If result is Error exn, p is rejected with exn.

If p is not pending, Lwt.wakeup_later_result raises Stdlib.Invalid_argument _, except if p is canceled. If p is canceled, Lwt.wakeup_later_result has no effect.

State query

type 'a state =
  1. | Return of 'a
  2. | Fail of exn
  3. | Sleep
val state : 'a t -> 'a state

Lwt.state p evaluates to the current state of promise p:

  • If p is fulfilled with value v, the result is Lwt.Return v.
  • If p is rejected with exception exn, the result is Lwt.Fail exn.
  • If p is pending, the result is Lwt.Sleep.

The constructor names are historical holdovers.

Deprecated

Implicit callback arguments

Using this mechanism is discouraged, because it is non-syntactic, and because it manipulates hidden state in module Lwt. It is recommended instead to pass additional values explicitly in tuples, or maintain explicit associative maps for them.

type 'a key

Keys into the implicit callback argument map, for implicit arguments of type 'a option.

The keys are abstract, but they are basically integers that are all distinct from each other.

See Lwt.with_value.

val new_key : unit -> 'a key

Creates a fresh implicit callback argument key.

The key is distinct from any other key created by the current process. The value None of type 'a option is immediately associated with the key.

See Lwt.with_value.

val get : 'a key -> 'a option

Retrieves the value currently associated with the given implicit callback argument key.

See Lwt.with_value.

val with_value : 'a key -> 'a option -> (unit -> 'b) -> 'b

Lwt.with_value k v f sets k to v in Lwt's internal implicit callback argument map, then runs f (), then restores the previous value associated with k.

Lwt maintains a single, global map, that can be used to β€œpass” extra arguments to callbacks:

let () =
+  let k : string Lwt.key = Lwt.new_key () in
+
+  let say_hello () =
+    match Lwt.get k with
+    | None -> assert false
+    | Some s -> Lwt_io.printl s
+  in
+
+  Lwt_main.run begin
+    Lwt.with_value k (Some "Hello world!") begin fun () ->
+      Lwt.bind
+        (Lwt_unix.sleep 1.)
+        (fun () -> say_hello ())
+    end
+  end
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

Note that the string Hello world! was passed to say_hello through the key k. Meanwhile, the only explicit argument of the callback say_hello is ().

The way this works is functions like Lwt.bind take a snapshot of the implicit argument map. Later, right before the callback is run, the map is restored to that snapshot. In other words, the map has the same state inside the callback as it did at the time the callback was registered.

To be more precise:

  • Lwt.with_value associates Some "Hello world!" with k, and runs the function passed to it.
  • This function contains the Lwt.bind.
  • OCaml's eager evaluation means the arguments are evaluated first. In particular, the Lwt_unix.sleep 1. promise is created.
  • Lwt.bind then attaches the callback in its second argument, the one which calls say_hello, to that sleep promise.
  • Lwt.bind also takes a snapshot of the current state of the implicit argument map, and pairs the callback with that snapshot.
  • The callback will not run for another second or so, when the sleep promise will be resolved.
  • Instead, Lwt.bind returns its result promise p_3. This causes Lwt.with_value to also return p_3, first restoring k to be associated with None.
  • Lwt_main.run gets the pending p_3, and blocks the whole process, with k associated with None.
  • One second later, the sleep I/O completes, resolving the sleep promise.
  • This triggers the say_hello callback. Right before the callback is called, the implicit argument map is restored to its snapshot, so k is associated with Some "Hello world!".
  • After the callback completes, Lwt again restores k to be associated with None.

The Lwt functions that take snapshots of the implicit callback argument map are exactly those which attach callbacks to promises: Lwt.bind and its variants >>= and let%lwt, Lwt.map and its variant >|=, Lwt.catch and its variant try%lwt, Lwt.finalize and its variant %lwt.finally, Lwt.try_bind, Lwt.on_success, Lwt.on_failure, Lwt.on_termination, and Lwt.on_any.

Lwt.with_value should only be called in the main thread, i.e. do not call it inside Lwt_preemptive.detach.

Immediate resolving

val wakeup : 'a u -> 'a -> unit

Lwt.wakeup r v is like Lwt.wakeup_later r v, except it guarantees that callbacks associated with r will be called immediately, deeper on the current stack.

In contrast, Lwt.wakeup_later may call callbacks immediately, or may queue them for execution on a shallower stack – though still before the next time Lwt blocks the process on I/O.

Using this function is discouraged, because calling it in a loop can exhaust the stack. The loop might be difficult to detect or predict, due to combined mutually-recursive calls between multiple modules and libraries.

Also, trying to use this function to guarantee the timing of callback calls for synchronization purposes is discouraged. This synchronization effect is obscure to readers. It is better to use explicit promises, or Lwt_mutex, Lwt_condition, and/or Lwt_mvar.

val wakeup_exn : _ u -> exn -> unit

Lwt.wakeup_exn r exn is like Lwt.wakeup_later_exn r exn, but has the same problems as Lwt.wakeup.

val wakeup_result : 'a u -> ('a, exn) result -> unit

Lwt.wakeup_result r result is like Lwt.wakeup_later_result r result, but has the same problems as Lwt.wakeup.

Linked lists of promises

val add_task_r : 'a u Lwt_sequence.t -> 'a t

Lwt.add_task_r sequence is equivalent to

let p, r = Lwt.task () in
+let node = Lwt_sequence.add_r r sequence in
+Lwt.on_cancel p (fun () -> Lwt_sequence.remove node);
+p
  • deprecated

    Use of this function is discouraged for two reasons:

    • Lwt_sequence should not be used outside Lwt.
    • This function only exists because it performs a minor internal optimization, which may be removed.
val add_task_l : 'a u Lwt_sequence.t -> 'a t

Like Lwt.add_task_r, but the equivalent code calls Lwt_sequence.add_l instead.

  • deprecated

    See add_task_r.

Yielding

val pause : unit -> unit t

Lwt.pause () creates a pending promise that is fulfilled after Lwt finishes calling all currently ready callbacks, i.e. it is fulfilled on the next β€œtick.”

Putting the rest of your computation into a callback of Lwt.pause () creates a β€œyield” that gives other callbacks a chance to run first.

For example, to break up a long-running computation, allowing I/O to be handled between chunks:

let () =
+  let rec handle_io () =
+    let%lwt () = Lwt_io.printl "Handling I/O" in
+    let%lwt () = Lwt_unix.sleep 0.1 in
+    handle_io ()
+  in
+
+  let rec compute n =
+    if n = 0 then
+      Lwt.return ()
+    else
+      let%lwt () =
+        if n mod 1_000_000 = 0 then
+          Lwt.pause ()
+        else
+          Lwt.return ()
+      in
+      compute (n - 1)
+  in
+
+  Lwt.async handle_io;
+  Lwt_main.run (compute 100_000_000)
+
+(* ocamlfind opt -linkpkg -thread -package lwt_ppx,lwt.unix code.ml && ./a.out *)

If you replace the call to Lwt.pause by Lwt.return in the program above, "Handling I/O" is printed only once. With Lwt.pause, it is printed several times, depending on the speed of your machine.

An alternative way to handle long-running computations is to detach them to preemptive threads using Lwt_preemptive.

Function lifters

val wrap : (unit -> 'a) -> 'a t

Lwt.wrap f applies f (). If f () returns a value v, Lwt.wrap returns Lwt.return v. If f () raises an exception exn, Lwt.wrap returns Lwt.fail exn.

val wrap1 : ('a -> 'b) -> 'a -> 'b t
val wrap2 : ('a -> 'b -> 'c) -> 'a -> 'b -> 'c t
val wrap3 : ('a -> 'b -> 'c -> 'd) -> 'a -> 'b -> 'c -> 'd t
val wrap4 : ('a -> 'b -> 'c -> 'd -> 'e) -> 'a -> 'b -> 'c -> 'd -> 'e t
val wrap5 : + ('a -> 'b -> 'c -> 'd -> 'e -> 'f) -> + 'a -> + 'b -> + 'c -> + 'd -> + 'e -> + 'f t
val wrap6 : + ('a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g) -> + 'a -> + 'b -> + 'c -> + 'd -> + 'e -> + 'f -> + 'g t
val wrap7 : + ('a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> 'h) -> + 'a -> + 'b -> + 'c -> + 'd -> + 'e -> + 'f -> + 'g -> + 'h t

As a β€œprototype,” Lwt_wrap1 f creates a promise-valued function g:

let g v =
+  try
+    let v' = f v in
+    Lwt.return v'
+  with exn ->
+    Lwt.fail exn

The remainder of the functions work analogously – they just work on f with larger numbers of arguments.

Note that there is an important difference to Lwt.wrap. These functions don't run f, nor create the final promise, immediately. In contrast, Lwt.wrap runs its argument f eagerly.

To get a suspended function instead of the eager execution of Lwt.wrap, use Lwt.wrap1.

Unscoped infix operators

Use the operators in module Lwt.Infix instead. Using these instances of the operators directly requires opening module Lwt, which brings an excessive number of other names into scope.

val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
val (<?>) : 'a t -> 'a t -> 'a t
val (<&>) : unit t -> unit t -> unit t
val (=<<) : ('a -> 'b t) -> 'a t -> 'b t
val (=|<) : ('a -> 'b) -> 'a t -> 'b t

Miscellaneous

val is_sleeping : _ t -> bool

Lwt.is_sleeping p is equivalent to Lwt.state p = Lwt.Sleep.

val ignore_result : _ t -> unit

An obsolete variant of Lwt.async.

Lwt.ignore_result p behaves as follows:

  • If p is already fulfilled, Lwt.ignore_result p does nothing.
  • If p is already rejected with exn, Lwt.ignore_result p raises exn immediately.
  • If p is pending, Lwt.ignore_result p does nothing, but if p becomes rejected later, the exception is passed to !Lwt.async_exception_hook.

Use of this function is discouraged for two reasons:

  • The behavior is different depending on whether p is rejected now or later.
  • The name is misleading, and has led to users thinking this function is analogous to Stdlib.ignore, i.e. that it waits for p to become resolved, completing any associated side effects along the way. In fact, the function that does that is ordinary Lwt.bind.
Runtime exception filters

Depending on the kind of programs that you write, you may need to treat exceptions thrown by the OCaml runtime (namely Out_of_memory and Stack_overflow) differently than all the other exceptions. This is because (a) these exceptions are not reproducible (in that they are thrown at different points of your program depending on the machine that your program runs on) and (b) recovering from these errors may be impossible.

The helpers below allow you to change the way that Lwt handles the two OCaml runtime exceptions Out_of_memory and Stack_overflow.

module Exception_filter : sig ... end
diff --git a/dev/lwt/Lwt_bytes/index.html b/dev/lwt/Lwt_bytes/index.html new file mode 100644 index 00000000..50ac764c --- /dev/null +++ b/dev/lwt/Lwt_bytes/index.html @@ -0,0 +1,42 @@ + +Lwt_bytes (lwt.Lwt_bytes)

Module Lwt_bytes

Byte arrays

val create : int -> t

Creates a new byte array of the given size.

val length : t -> int

Returns the length of the given byte array.

Access

val get : t -> int -> char

get buffer offset returns the byte at offset offset in buffer.

val set : t -> int -> char -> unit

get buffer offset value changes the value of the byte at offset offset in buffer to value.

val unsafe_get : t -> int -> char

Same as get but without bounds checking.

val unsafe_set : t -> int -> char -> unit

Same as set but without bounds checking.

Conversions

val of_bytes : bytes -> t

of_bytes buf returns a newly allocated byte array with the same contents as buf.

val of_string : string -> t

of_string buf returns a newly allocated byte array with the same contents as buf.

val to_bytes : t -> bytes

to_bytes buf returns newly allocated bytes with the same contents as buf.

val to_string : t -> string

to_string buf returns a newly allocated string with the same contents as buf.

Copying

val blit : t -> int -> t -> int -> int -> unit

blit buf1 ofs1 buf2 ofs2 len copies len bytes from buf1 starting at offset ofs1 to buf2 starting at offset ofs2.

val blit_from_string : string -> int -> t -> int -> int -> unit

Same as blit but the first buffer is a String.t instead of a byte array.

val blit_from_bytes : bytes -> int -> t -> int -> int -> unit

Same as blit but the first buffer is a Bytes.t instead of a byte array.

val blit_to_bytes : t -> int -> bytes -> int -> int -> unit

Same as blit but the second buffer is a Bytes.t instead of a byte array.

val unsafe_blit : t -> int -> t -> int -> int -> unit

Same as blit but without bound checking.

val unsafe_blit_from_bytes : bytes -> int -> t -> int -> int -> unit

Same as Lwt_bytes.blit_from_bytes but without bounds checking.

val unsafe_blit_from_string : string -> int -> t -> int -> int -> unit

Same as Lwt_bytes.blit_from_string but without bounds checking.

val unsafe_blit_to_bytes : t -> int -> bytes -> int -> int -> unit

Same as Lwt_bytes.blit_to_bytes but without bounds checking.

val proxy : t -> int -> int -> t

proxy buffer offset length creates a ``proxy''. The returned byte array share the data of buffer but with different bounds.

val extract : t -> int -> int -> t

extract buffer offset length creates a new byte array of length length and copy the length bytes of buffer at offset into it.

val copy : t -> t

copy buffer creates a copy of the given byte array.

Filling

val fill : t -> int -> int -> char -> unit

fill buffer offset length value puts value in all length bytes of buffer starting at offset offset.

val unsafe_fill : t -> int -> int -> char -> unit

Same as fill but without bounds checking.

IOs

The following functions behave similarly to the ones in Lwt_unix, except they use byte arrays instead of Bytes.t, and they never perform extra copies of the data.

val read : Lwt_unix.file_descr -> t -> int -> int -> int Lwt.t
val write : Lwt_unix.file_descr -> t -> int -> int -> int Lwt.t
val recv : + Lwt_unix.file_descr -> + t -> + int -> + int -> + Unix.msg_flag list -> + int Lwt.t

Not implemented on Windows.

val send : + Lwt_unix.file_descr -> + t -> + int -> + int -> + Unix.msg_flag list -> + int Lwt.t

Not implemented on Windows.

val recvfrom : + Lwt_unix.file_descr -> + t -> + int -> + int -> + Unix.msg_flag list -> + (int * Unix.sockaddr) Lwt.t

Not implemented on Windows.

val sendto : + Lwt_unix.file_descr -> + t -> + int -> + int -> + Unix.msg_flag list -> + Unix.sockaddr -> + int Lwt.t

Not implemented on Windows.

type io_vector = {
  1. iov_buffer : t;
  2. iov_offset : int;
  3. iov_length : int;
}
val io_vector : buffer:t -> offset:int -> length:int -> io_vector
val recv_msg : + socket:Lwt_unix.file_descr -> + io_vectors:io_vector list -> + (int * Unix.file_descr list) Lwt.t

Not implemented on Windows.

val send_msg : + socket:Lwt_unix.file_descr -> + io_vectors:io_vector list -> + fds:Unix.file_descr list -> + int Lwt.t

Not implemented on Windows.

Memory mapped files

val map_file : + fd:Unix.file_descr -> + ?pos:int64 -> + shared:bool -> + ?size:int -> + unit -> + t

map_file ~fd ?pos ~shared ?size () maps the file descriptor fd to an array of bytes.

val mapped : t -> bool

mapped buffer returns true iff buffer is a memory mapped file.

type advice =
  1. | MADV_NORMAL
  2. | MADV_RANDOM
  3. | MADV_SEQUENTIAL
  4. | MADV_WILLNEED
  5. | MADV_DONTNEED
  6. | MADV_MERGEABLE
  7. | MADV_UNMERGEABLE
  8. | MADV_HUGEPAGE
  9. | MADV_NOHUGEPAGE

Type of advise that can be sent to the kernel by the program. See the manual madvise(2) for a description of each.

val madvise : t -> int -> int -> advice -> unit

madvise buffer pos len advice advises the kernel how the program will use the memory mapped file between pos and pos + len.

This call is not available on windows.

val page_size : int

Size of pages.

val mincore : t -> int -> bool array -> unit

mincore buffer offset states tests whether the given pages are in the system memory (the RAM). The offset argument must be a multiple of page_size. states is used to store the result; each cases is true if the corresponding page is in RAM and false otherwise.

This call is not available on windows and cygwin.

val wait_mincore : t -> int -> unit Lwt.t

wait_mincore buffer offset waits until the page containing the byte at offset offset is in RAM.

This functions is not available on windows and cygwin.

diff --git a/dev/lwt/Lwt_condition/index.html b/dev/lwt/Lwt_condition/index.html new file mode 100644 index 00000000..566769ea --- /dev/null +++ b/dev/lwt/Lwt_condition/index.html @@ -0,0 +1,2 @@ + +Lwt_condition (lwt.Lwt_condition)

Module Lwt_condition

Conditions

Condition variables to synchronize between threads.

type 'a t

Condition variable type. The type parameter denotes the type of value propagated from notifier to waiter.

val create : unit -> 'a t

create () creates a new condition variable.

val wait : ?mutex:Lwt_mutex.t -> 'a t -> 'a Lwt.t

wait mutex condvar will cause the current thread to block, awaiting notification for a condition variable, condvar. If provided, the mutex must have been previously locked (within the scope of Lwt_mutex.with_lock, for example) and is temporarily unlocked until the condition is notified. Upon notification, mutex is re-locked before wait returns and the thread's activity is resumed. When the awaited condition is notified, the value parameter passed to signal is returned.

val signal : 'a t -> 'a -> unit

signal condvar value notifies that a condition is ready. A single waiting thread will be awoken and will receive the notification value which will be returned from wait. Note that condition notification is not "sticky", i.e. if there is no waiter when signal is called, the notification will be missed and the value discarded.

val broadcast : 'a t -> 'a -> unit

broadcast condvar value notifies all waiting threads. Each will be awoken in turn and will receive the same notification value.

val broadcast_exn : 'a t -> exn -> unit

broadcast_exn condvar exn fails all waiting threads with exception exn.

  • since 2.6.0
diff --git a/dev/lwt/Lwt_config/index.html b/dev/lwt/Lwt_config/index.html new file mode 100644 index 00000000..7c9c6c5c --- /dev/null +++ b/dev/lwt/Lwt_config/index.html @@ -0,0 +1,2 @@ + +Lwt_config (lwt.Lwt_config)

Module Lwt_config

include module type of struct include Lwt_features end
val android : bool
val libev_default : bool
val _HAVE_LIBEV : bool
val _HAVE_PTHREAD : bool
val _HAVE_EVENTFD : bool
val _HAVE_FD_PASSING : bool
val _HAVE_GETCPU : bool
val _HAVE_AFFINITY : bool
val _HAVE_GET_CREDENTIALS_LINUX : bool
val _HAVE_GET_CREDENTIALS_NETBSD : bool
val _HAVE_GET_CREDENTIALS_OPENBSD : bool
val _HAVE_GET_CREDENTIALS_FREEBSD : bool
val _HAVE_GETPEEREID : bool
val _HAVE_FDATASYNC : bool
val _HAVE_NETDB_REENTRANT : bool
val _HAVE_REENTRANT_HOSTENT : bool
val _HAVE_ST_MTIM_TV_NSEC : bool
val _HAVE_ST_MTIMESPEC_TV_NSEC : bool
val _HAVE_ST_MTIMENSEC : bool
val _HAVE_BSD_MINCORE : bool
val _HAVE_ACCEPT4 : bool
val _HAVE_GET_CREDENTIALS : bool
diff --git a/dev/lwt/Lwt_engine/Ev_backend/index.html b/dev/lwt/Lwt_engine/Ev_backend/index.html new file mode 100644 index 00000000..4c8794f1 --- /dev/null +++ b/dev/lwt/Lwt_engine/Ev_backend/index.html @@ -0,0 +1,2 @@ + +Ev_backend (lwt.Lwt_engine.Ev_backend)

Module Lwt_engine.Ev_backend

type t
val default : t
val select : t
val poll : t
val epoll : t
val kqueue : t
val devpoll : t
val port : t
val pp : Stdlib.Format.formatter -> t -> unit
diff --git a/dev/lwt/Lwt_engine/Versioned/class-libev_1/index.html b/dev/lwt/Lwt_engine/Versioned/class-libev_1/index.html new file mode 100644 index 00000000..63e61a3a --- /dev/null +++ b/dev/lwt/Lwt_engine/Versioned/class-libev_1/index.html @@ -0,0 +1,2 @@ + +libev_1 (lwt.Lwt_engine.Versioned.libev_1)

Class Versioned.libev_1

Old version of Lwt_engine.libev. The current Lwt_engine.libev allows selecting the libev back end.

inherit t
val loop : ev_loop
method loop : ev_loop
diff --git a/dev/lwt/Lwt_engine/Versioned/class-libev_2/index.html b/dev/lwt/Lwt_engine/Versioned/class-libev_2/index.html new file mode 100644 index 00000000..5f3b9e9b --- /dev/null +++ b/dev/lwt/Lwt_engine/Versioned/class-libev_2/index.html @@ -0,0 +1,2 @@ + +libev_2 (lwt.Lwt_engine.Versioned.libev_2)

Class Versioned.libev_2

Since Lwt 3.0.0, this is just an alias for Lwt_engine.libev.

inherit t
val loop : ev_loop
method loop : ev_loop
diff --git a/dev/lwt/Lwt_engine/Versioned/index.html b/dev/lwt/Lwt_engine/Versioned/index.html new file mode 100644 index 00000000..2ff30a14 --- /dev/null +++ b/dev/lwt/Lwt_engine/Versioned/index.html @@ -0,0 +1,2 @@ + +Versioned (lwt.Lwt_engine.Versioned)

Module Lwt_engine.Versioned

class libev_1 : object ... end

Old version of Lwt_engine.libev. The current Lwt_engine.libev allows selecting the libev back end.

class libev_2 : ?backend:Ev_backend.t -> unit -> object ... end

Since Lwt 3.0.0, this is just an alias for Lwt_engine.libev.

diff --git a/dev/lwt/Lwt_engine/class-abstract/index.html b/dev/lwt/Lwt_engine/class-abstract/index.html new file mode 100644 index 00000000..4ab27273 --- /dev/null +++ b/dev/lwt/Lwt_engine/class-abstract/index.html @@ -0,0 +1,9 @@ + +abstract (lwt.Lwt_engine.abstract)

Class Lwt_engine.abstract

Abstract class for engines.

method destroy : unit

Destroy the engine, remove all its events and free its associated resources.

method transfer : abstract -> unit

transfer engine moves all events from the current engine to engine. Note that timers are reset in the destination engine, i.e. if a timer with a delay of 2 seconds was registered 1 second ago it will occur in 2 seconds in the destination engine.

Event loop methods

method virtual iter : bool -> unit
method fork : unit
method on_readable : Unix.file_descr -> (event -> unit) -> event
method on_writable : Unix.file_descr -> (event -> unit) -> event
method on_timer : float -> bool -> (event -> unit) -> event
method fake_io : Unix.file_descr -> unit
method readable_count : int
method writable_count : int
method timer_count : int
method forwards_signal : int -> bool

Backend methods

Notes:

method private virtual cleanup : unit

Cleanup resources associated with the engine.

method private virtual register_readable : Unix.file_descr -> + (unit -> unit) -> + unit Lazy.t
method private virtual register_writable : Unix.file_descr -> + (unit -> unit) -> + unit Lazy.t
method private virtual register_timer : float -> + bool -> + (unit -> unit) -> + unit Lazy.t
diff --git a/dev/lwt/Lwt_engine/class-libev/index.html b/dev/lwt/Lwt_engine/class-libev/index.html new file mode 100644 index 00000000..8cd413af --- /dev/null +++ b/dev/lwt/Lwt_engine/class-libev/index.html @@ -0,0 +1,2 @@ + +libev (lwt.Lwt_engine.libev)

Class Lwt_engine.libev

Engine based on libev. If not compiled with libev support, the creation of the class will raise Lwt_sys.Not_available.

inherit t
val loop : ev_loop

The libev loop used for this engine.

method loop : ev_loop

Returns loop.

diff --git a/dev/lwt/Lwt_engine/class-poll_based/index.html b/dev/lwt/Lwt_engine/class-poll_based/index.html new file mode 100644 index 00000000..cb8c01c0 --- /dev/null +++ b/dev/lwt/Lwt_engine/class-poll_based/index.html @@ -0,0 +1,4 @@ + +poll_based (lwt.Lwt_engine.poll_based)

Class Lwt_engine.poll_based

Abstract class for engines based on a poll-like function.

inherit t
method private virtual poll : (Unix.file_descr * bool * bool) list -> + float -> + (Unix.file_descr * bool * bool) list

poll fds tiomeout, where fds is a list of tuples of the form (fd, check_readable, check_writable), waits for either:

  • one of the file descriptor with check_readable set to true to become readable
  • one of the file descriptor with check_writable set to true to become writable
  • timeout to expire

and returns the list of file descriptors with their readable and writable status.

diff --git a/dev/lwt/Lwt_engine/class-select/index.html b/dev/lwt/Lwt_engine/class-select/index.html new file mode 100644 index 00000000..3df6f344 --- /dev/null +++ b/dev/lwt/Lwt_engine/class-select/index.html @@ -0,0 +1,6 @@ + +select (lwt.Lwt_engine.select)

Class Lwt_engine.select

Engine based on Unix.select.

inherit abstract
method iter : bool -> unit
method private cleanup : unit
method private register_readable : Unix.file_descr -> + (unit -> unit) -> + unit Lazy.t
method private register_writable : Unix.file_descr -> + (unit -> unit) -> + unit Lazy.t
method private register_timer : float -> bool -> (unit -> unit) -> unit Lazy.t
diff --git a/dev/lwt/Lwt_engine/class-select_based/index.html b/dev/lwt/Lwt_engine/class-select_based/index.html new file mode 100644 index 00000000..b3c63e22 --- /dev/null +++ b/dev/lwt/Lwt_engine/class-select_based/index.html @@ -0,0 +1,5 @@ + +select_based (lwt.Lwt_engine.select_based)

Class Lwt_engine.select_based

Abstract class for engines based on a select-like function.

inherit t
method private virtual select : Unix.file_descr list -> + Unix.file_descr list -> + float -> + Unix.file_descr list * Unix.file_descr list

select fds_r fds_w timeout waits for either:

  • one of the file descriptor of fds_r to become readable
  • one of the file descriptor of fds_w to become writable
  • timeout to expire

and returns the list of readable file descriptor and the list of writable file descriptors.

diff --git a/dev/lwt/Lwt_engine/class-type-t/index.html b/dev/lwt/Lwt_engine/class-type-t/index.html new file mode 100644 index 00000000..b0f4c618 --- /dev/null +++ b/dev/lwt/Lwt_engine/class-type-t/index.html @@ -0,0 +1,6 @@ + +t (lwt.Lwt_engine.t)

Class type Lwt_engine.t

Type of engines.

inherit abstract
method iter : bool -> unit
method private cleanup : unit
method private register_readable : Unix.file_descr -> + (unit -> unit) -> + unit Lazy.t
method private register_writable : Unix.file_descr -> + (unit -> unit) -> + unit Lazy.t
method private register_timer : float -> bool -> (unit -> unit) -> unit Lazy.t
diff --git a/dev/lwt/Lwt_engine/index.html b/dev/lwt/Lwt_engine/index.html new file mode 100644 index 00000000..6dfc29b0 --- /dev/null +++ b/dev/lwt/Lwt_engine/index.html @@ -0,0 +1,2 @@ + +Lwt_engine (lwt.Lwt_engine)

Module Lwt_engine

Lwt unix main loop engine

Events

type event

Type of events. An event represent a callback registered to be called when some event occurs.

val stop_event : event -> unit

stop_event event stops the given event.

val fake_event : event

Event which does nothing when stopped.

Event loop functions

val iter : bool -> unit

iter block performs one iteration of the main loop. If block is true the function must block until one event becomes available, otherwise it should just check for available events and return immediately.

val on_readable : Unix.file_descr -> (event -> unit) -> event

on_readable fd f calls f each time fd becomes readable.

val on_writable : Unix.file_descr -> (event -> unit) -> event

on_readable fd f calls f each time fd becomes writable.

val on_timer : float -> bool -> (event -> unit) -> event

on_timer delay repeat f calls f one time after delay seconds. If repeat is true then f is called each delay seconds, otherwise it is called only one time.

val readable_count : unit -> int

Returns the number of events waiting for a file descriptor to become readable.

val writable_count : unit -> int

Returns the number of events waiting for a file descriptor to become writable.

val timer_count : unit -> int

Returns the number of registered timers.

val fake_io : Unix.file_descr -> unit

Simulates activity on the given file descriptor.

val fork : unit -> unit

Called internally by Lwt_unix.fork to make sure we don't get strange behaviour

val forwards_signal : int -> bool

forwards_signal signum is true if the engine will call Lwt_unix.handle_signal when signal signum occurs. In this case, Lwt will not install its own signal handler.

Normally, this just returns false, but when Lwt is used in combination with other IO libraries, this allows sharing e.g. the SIGCHLD handler.

Engines

An engine represents a set of functions used to register different kinds of callbacks for different kinds of events.

class virtual abstract : object ... end

Abstract class for engines.

class type t = object ... end

Type of engines.

Predefined engines

type ev_loop
module Ev_backend : sig ... end

Type of libev loops.

class libev : ?backend:Ev_backend.t -> unit -> object ... end

Engine based on libev. If not compiled with libev support, the creation of the class will raise Lwt_sys.Not_available.

class select : t

Engine based on Unix.select.

class virtual select_based : object ... end

Abstract class for engines based on a select-like function.

class virtual poll_based : object ... end

Abstract class for engines based on a poll-like function.

The current engine

val get : unit -> t

get () returns the engine currently in use.

val set : ?transfer:bool -> ?destroy:bool -> t -> unit

set ?transfer ?destroy engine replaces the current engine by the given one.

If transfer is true (the default) all events from the current engine are transferred to the new one.

If destroy is true (the default) then the current engine is destroyed before being replaced.

module Versioned : sig ... end
diff --git a/dev/lwt/Lwt_features/index.html b/dev/lwt/Lwt_features/index.html new file mode 100644 index 00000000..031b68f6 --- /dev/null +++ b/dev/lwt/Lwt_features/index.html @@ -0,0 +1,2 @@ + +Lwt_features (lwt.Lwt_features)

Module Lwt_features

val android : bool
val libev_default : bool
val _HAVE_LIBEV : bool
val _HAVE_PTHREAD : bool
val _HAVE_EVENTFD : bool
val _HAVE_FD_PASSING : bool
val _HAVE_GETCPU : bool
val _HAVE_AFFINITY : bool
val _HAVE_GET_CREDENTIALS_LINUX : bool
val _HAVE_GET_CREDENTIALS_NETBSD : bool
val _HAVE_GET_CREDENTIALS_OPENBSD : bool
val _HAVE_GET_CREDENTIALS_FREEBSD : bool
val _HAVE_GETPEEREID : bool
val _HAVE_FDATASYNC : bool
val _HAVE_NETDB_REENTRANT : bool
val _HAVE_REENTRANT_HOSTENT : bool
val _HAVE_ST_MTIM_TV_NSEC : bool
val _HAVE_ST_MTIMESPEC_TV_NSEC : bool
val _HAVE_ST_MTIMENSEC : bool
val _HAVE_BSD_MINCORE : bool
val _HAVE_ACCEPT4 : bool
diff --git a/dev/lwt/Lwt_fmt/index.html b/dev/lwt/Lwt_fmt/index.html new file mode 100644 index 00000000..4a139650 --- /dev/null +++ b/dev/lwt/Lwt_fmt/index.html @@ -0,0 +1,20 @@ + +Lwt_fmt (lwt.Lwt_fmt)

Module Lwt_fmt

Format API for Lwt-powered IOs

This module bridges the gap between Stdlib.Format and Lwt. Although it is not required, it is recommended to use this module with the Fmt library.

Compared to regular formatting function, the main difference is that printing statements will now return promises instead of blocking.

val printf : ('a, Stdlib.Format.formatter, unit, unit Lwt.t) format4 -> 'a

Returns a promise that prints on the standard output. Similar to Stdlib.Format.printf.

val eprintf : ('a, Stdlib.Format.formatter, unit, unit Lwt.t) format4 -> 'a

Returns a promise that prints on the standard error. Similar to Stdlib.Format.eprintf.

Formatters

type formatter

Lwt enabled formatters

type order =
  1. | String of string * int * int
    (*

    String (s, off, len) indicate the output of s at offset off and length len.

    *)
  2. | Flush
    (*

    Flush operation

    *)
val make_stream : unit -> order Lwt_stream.t * formatter

make_stream () returns a formatter and a stream of all the writing order given on that stream.

val of_channel : Lwt_io.output_channel -> formatter

of_channel oc creates a formatter that writes to the channel oc.

val stdout : formatter

Formatter printing on Lwt_io.stdout.

val stderr : formatter

Formatter printing on Lwt_io.stdout.

val make_formatter : + commit:(unit -> unit Lwt.t) -> + fmt:Stdlib.Format.formatter -> + unit -> + formatter

make_formatter ~commit ~fmt creates a new lwt formatter based on the Stdlib.Format.formatter fmt. The commit function will be called by the printing functions to update the underlying channel.

val get_formatter : formatter -> Stdlib.Format.formatter

get_formatter fmt returns the underlying Stdlib.Format.formatter. To access the underlying formatter during printing, it is recommended to use %t and %a.

Printing

val fprintf : + formatter -> + ('a, Stdlib.Format.formatter, unit, unit Lwt.t) format4 -> + 'a
val kfprintf : + (formatter -> unit Lwt.t -> 'a) -> + formatter -> + ('b, Stdlib.Format.formatter, unit, 'a) format4 -> + 'b
val ifprintf : + formatter -> + ('a, Stdlib.Format.formatter, unit, unit Lwt.t) format4 -> + 'a
val ikfprintf : + (formatter -> unit Lwt.t -> 'a) -> + formatter -> + ('b, Stdlib.Format.formatter, unit, 'a) format4 -> + 'b
val flush : formatter -> unit Lwt.t

flush fmt flushes the formatter (as with Stdlib.Format.pp_print_flush) and executes all the printing action on the underlying channel.

Low level functions

val write_order : Lwt_io.output_channel -> order -> unit Lwt.t

write_order oc o applies the order o on the channel oc.

val write_pending : formatter -> unit Lwt.t

Write all the pending orders of a formatter. Warning: This function flush neither the internal format queues nor the underlying channel and is intended for low level use only. You should probably use flush instead.

diff --git a/dev/lwt/Lwt_gc/index.html b/dev/lwt/Lwt_gc/index.html new file mode 100644 index 00000000..5005ac35 --- /dev/null +++ b/dev/lwt/Lwt_gc/index.html @@ -0,0 +1,2 @@ + +Lwt_gc (lwt.Lwt_gc)

Module Lwt_gc

Interaction with the garbage collector

This module offers a convenient way to add a finaliser launching a thread to a value, without having to use Lwt_unix.run in the finaliser.

val finalise : ('a -> unit Lwt.t) -> 'a -> unit

finalise f x ensures f x is evaluated after x has been garbage collected. If f x yields, then Lwt will wait for its termination at the end of the program.

Note that f x is not called at garbage collection time, but later in the main loop.

val finalise_or_exit : ('a -> unit Lwt.t) -> 'a -> unit

finalise_or_exit f x call f x when x is garbage collected or (exclusively) when the program exits.

diff --git a/dev/lwt/Lwt_io/BE/index.html b/dev/lwt/Lwt_io/BE/index.html new file mode 100644 index 00000000..49f4d01b --- /dev/null +++ b/dev/lwt/Lwt_io/BE/index.html @@ -0,0 +1,2 @@ + +BE (lwt.Lwt_io.BE)

Module Lwt_io.BE

Reading/writing of numbers in big-endian

Reading

val read_int : input_channel -> int Lwt.t

Reads a 32-bits integer as an ocaml int

val read_int16 : input_channel -> int Lwt.t
val read_int32 : input_channel -> int32 Lwt.t
val read_int64 : input_channel -> int64 Lwt.t
val read_float32 : input_channel -> float Lwt.t

Reads an IEEE single precision floating point value

val read_float64 : input_channel -> float Lwt.t

Reads an IEEE double precision floating point value

Writing

val write_int : output_channel -> int -> unit Lwt.t

Writes an ocaml int as a 32-bits integer

val write_int16 : output_channel -> int -> unit Lwt.t
val write_int32 : output_channel -> int32 -> unit Lwt.t
val write_int64 : output_channel -> int64 -> unit Lwt.t
val write_float32 : output_channel -> float -> unit Lwt.t

Writes an IEEE single precision floating point value

val write_float64 : output_channel -> float -> unit Lwt.t

Writes an IEEE double precision floating point value

diff --git a/dev/lwt/Lwt_io/LE/index.html b/dev/lwt/Lwt_io/LE/index.html new file mode 100644 index 00000000..95b5c4e0 --- /dev/null +++ b/dev/lwt/Lwt_io/LE/index.html @@ -0,0 +1,2 @@ + +LE (lwt.Lwt_io.LE)

Module Lwt_io.LE

Reading/writing of numbers in little-endian

Reading

val read_int : input_channel -> int Lwt.t

Reads a 32-bits integer as an ocaml int

val read_int16 : input_channel -> int Lwt.t
val read_int32 : input_channel -> int32 Lwt.t
val read_int64 : input_channel -> int64 Lwt.t
val read_float32 : input_channel -> float Lwt.t

Reads an IEEE single precision floating point value

val read_float64 : input_channel -> float Lwt.t

Reads an IEEE double precision floating point value

Writing

val write_int : output_channel -> int -> unit Lwt.t

Writes an ocaml int as a 32-bits integer

val write_int16 : output_channel -> int -> unit Lwt.t
val write_int32 : output_channel -> int32 -> unit Lwt.t
val write_int64 : output_channel -> int64 -> unit Lwt.t
val write_float32 : output_channel -> float -> unit Lwt.t

Writes an IEEE single precision floating point value

val write_float64 : output_channel -> float -> unit Lwt.t

Writes an IEEE double precision floating point value

diff --git a/dev/lwt/Lwt_io/Versioned/index.html b/dev/lwt/Lwt_io/Versioned/index.html new file mode 100644 index 00000000..cd0d9643 --- /dev/null +++ b/dev/lwt/Lwt_io/Versioned/index.html @@ -0,0 +1,15 @@ + +Versioned (lwt.Lwt_io.Versioned)

Module Lwt_io.Versioned

Versioned variants of APIs undergoing breaking changes.

val establish_server_1 : + ?fd:Lwt_unix.file_descr -> + ?buffer_size:int -> + ?backlog:int -> + Unix.sockaddr -> + ((input_channel * output_channel) -> unit) -> + server

Old version of Lwt_io.establish_server. The current Lwt_io.establish_server automatically closes channels passed to the callback, and notifies the caller when the server's listening socket is bound.

  • since 2.7.0
val establish_server_2 : + ?fd:Lwt_unix.file_descr -> + ?buffer_size:int -> + ?backlog:int -> + ?no_close:bool -> + Unix.sockaddr -> + ((input_channel * output_channel) -> unit Lwt.t) -> + server Lwt.t

Since Lwt 3.0.0, this is just an alias for Lwt_io.establish_server.

  • since 2.7.0
val shutdown_server_1 : server -> unit

Old version of Lwt_io.shutdown_server. The current Lwt_io.shutdown_server returns a promise, which resolves when the server's listening socket is closed.

  • since 2.7.0
val shutdown_server_2 : server -> unit Lwt.t

Since Lwt 3.0.0, this is just an alias for Lwt_io.shutdown_server.

  • since 2.7.0
diff --git a/dev/lwt/Lwt_io/index.html b/dev/lwt/Lwt_io/index.html new file mode 100644 index 00000000..df54eae0 --- /dev/null +++ b/dev/lwt/Lwt_io/index.html @@ -0,0 +1,125 @@ + +Lwt_io (lwt.Lwt_io)

Module Lwt_io

Buffered byte channels

A channel is a high-level object for performing input/output (IO). It allows to read/write from/to the outside world in an efficient way, by minimising the number of system calls.

An output channel is used to send data and an input channel is used to receive data.

If you are familiar with buffered channels you may be familiar too with the flush operation. Note that byte channels of this module are automatically flushed when there is nothing else to do (i.e. before the program becomes idle), so this means that you no longer have to write:

eprintf "log message\n";
+flush stderr;

to have your messages displayed.

Note about errors: input functions of this module raise End_of_file when the end-of-file is reached (i.e. when the read function returns 0). Other exceptions are ones caused by the backend read/write functions, such as Unix.Unix_error.

exception Channel_closed of string

Exception raised when a channel is closed. The parameter is a description of the channel.

Types

type 'mode channel

Type of buffered byte channels

type input

Input mode

type output

Output mode

type 'a mode =
  1. | Input : input mode
  2. | Output : output mode

Channel mode

val input : input mode

input input mode representation

val output : output mode

output output mode representation

type input_channel = input channel

Type of input channels

type output_channel = output channel

Type of output channels

val mode : 'a channel -> 'a mode

mode ch returns the mode of a channel

Well-known instances

val stdin : input_channel

The standard input, it reads data from Lwt_unix.stdin

val stdout : output_channel

The standard output, it writes data to Lwt_unix.stdout

val stderr : output_channel

The standard output for error messages, it writes data to Lwt_unix.stderr

val zero : input_channel

Inputs which returns always '\x00'

val null : output_channel

Output which drops everything

Channels creation/manipulation

val pipe : + ?cloexec:bool -> + ?in_buffer:Lwt_bytes.t -> + ?out_buffer:Lwt_bytes.t -> + unit -> + input_channel * output_channel

pipe ?cloexec ?in_buffer ?out_buffer () creates a pipe using Lwt_unix.pipe and makes two channels from the two returned file descriptors

val make : + ?buffer:Lwt_bytes.t -> + ?close:(unit -> unit Lwt.t) -> + ?seek:(int64 -> Unix.seek_command -> int64 Lwt.t) -> + mode:'mode mode -> + (Lwt_bytes.t -> int -> int -> int Lwt.t) -> + 'mode channel

make ?buffer ?close ~mode perform_io is the main function for creating new channels.

  • parameter buffer

    user-supplied buffer. When this argument is present, its value will be used as the buffer for the created channel. The size of buffer must conform to the limitations described in set_default_buffer_size. When this argument is not present, a new internal buffer of default size will be allocated for this channel.

    Warning: do not use the same buffer for simultaneous work with more than one channel.

    There are other functions in this module that take a buffer argument, sharing the same semantics.

  • parameter close

    close function of the channel. It defaults to Lwt.return

  • parameter perform_io

    is the read or write function. It is called when more input is needed or when the buffer need to be flushed.

val of_bytes : mode:'mode mode -> Lwt_bytes.t -> 'mode channel

Create a channel from a byte array. Reading/writing is done directly on the provided array.

val of_fd : + ?buffer:Lwt_bytes.t -> + ?close:(unit -> unit Lwt.t) -> + mode:'mode mode -> + Lwt_unix.file_descr -> + 'mode channel

of_fd ?buffer ?close ~mode fd creates a channel from a file descriptor.

  • parameter close

    defaults to closing the file descriptor.

val of_unix_fd : + ?buffer:Lwt_bytes.t -> + ?close:(unit -> unit Lwt.t) -> + mode:'mode mode -> + Unix.file_descr -> + 'mode channel

of_unix_fd ?buffer ?close ~mode fd is a short-hand for:

of_fd ?buffer ?close (Lwt_unix.of_unix_file_descr fd)

val close : 'a channel -> unit Lwt.t

close ch closes the given channel. If ch is an output channel, it performs all pending actions, flushes it and closes it. If ch is an input channel, it just closes it immediately.

close returns the result of the close function of the channel. Multiple calls to close will return exactly the same value.

Note: you cannot use close on channels obtained with atomic.

val abort : 'a channel -> unit Lwt.t

abort ch abort current operations and close the channel immediately.

val atomic : ('a channel -> 'b Lwt.t) -> 'a channel -> 'b Lwt.t

atomic f transforms a sequence of io operations into one single atomic io operation.

Note:

  • the channel passed to f is invalid after f terminates
  • atomic can be called inside another atomic
val file_length : string -> int64 Lwt.t

Retrieves the length of the file at the given path. If the path refers to a directory, the returned promise is rejected with Unix.(Unix_error (EISDIR, _, _)).

val buffered : 'a channel -> int

buffered oc returns the number of bytes in the buffer

val flush : output_channel -> unit Lwt.t

flush oc performs all pending writes on oc

val flush_all : unit -> unit Lwt.t

flush_all () flushes all open output channels

val buffer_size : 'a channel -> int

Returns the size of the internal buffer.

val resize_buffer : 'a channel -> int -> unit Lwt.t

Resize the internal buffer to the given size

val is_busy : 'a channel -> bool

is_busy channel returns whether the given channel is currently busy. A channel is busy when there is at least one job using it that has not yet terminated.

val is_closed : 'a channel -> bool

is_closed channel returns whether the given channel is currently closed.

  • since 4.2.0

Random access

val position : 'a channel -> int64

position ch Returns the current position in the channel.

val set_position : 'a channel -> int64 -> unit Lwt.t

set_position ch pos Sets the position in the output channel. This does not work if the channel does not support random access.

val length : 'a channel -> int64 Lwt.t

Returns the length of the channel in bytes

Reading

Note: except for functions dealing with streams (read_chars and read_lines) all functions are atomic.

val read_char : input_channel -> char Lwt.t

read_char ic reads the next character of ic.

  • raises End_of_file

    if the end of the file is reached

val read_char_opt : input_channel -> char option Lwt.t

Same as Lwt_io.read_char, but does not raise End_of_file on end of input

val read_chars : input_channel -> char Lwt_stream.t

read_chars ic returns a stream holding all characters of ic

val read_line : input_channel -> string Lwt.t

read_line ic reads one complete line from ic and returns it without the end of line. End of line is either "\n" or "\r\n".

If the end of input is reached before reading any character, End_of_file is raised. If it is reached before reading an end of line but characters have already been read, they are returned.

val read_line_opt : input_channel -> string option Lwt.t

Same as read_line but do not raise End_of_file on end of input.

val read_lines : input_channel -> string Lwt_stream.t

read_lines ic returns a stream holding all lines of ic

val read : ?count:int -> input_channel -> string Lwt.t

If ~count is specified, read ~count ic reads at most ~count bytes from ic in one read operation. Note that fewer than ~count bytes can be read. This can happen for multiple reasons, including end of input, or no more data currently available. Check the size of the resulting string. read resolves with "" if the input channel is already at the end of input.

If ~count is not specified, read ic reads all bytes until the end of input.

val read_into : input_channel -> bytes -> int -> int -> int Lwt.t

read_into ic buffer offset length reads up to length bytes, stores them in buffer at offset offset, and returns the number of bytes read.

Note: read_into does not raise End_of_file, it returns a length of 0 instead.

val read_into_exactly : input_channel -> bytes -> int -> int -> unit Lwt.t

read_into_exactly ic buffer offset length reads exactly length bytes and stores them in buffer at offset offset.

  • raises End_of_file

    on end of input

val read_into_bigstring : + input_channel -> + Lwt_bytes.t -> + int -> + int -> + int Lwt.t
val read_into_exactly_bigstring : + input_channel -> + Lwt_bytes.t -> + int -> + int -> + unit Lwt.t
val read_value : input_channel -> 'a Lwt.t

read_value channel reads a marshaled value from channel; it corresponds to the standard library's Stdlib.Marshal.from_channel. The corresponding writing function is write_value.

Note that reading marshaled values is not, in general, type-safe. See the warning in the description of module Stdlib.Marshal for details. The short version is: if you read a value of one type, such as string, when a value of another type, such as int has actually been marshaled to channel, you may get arbitrary behavior, including segmentation faults, access violations, security bugs, etc.

Writing

Note: as for reading functions, all functions except write_chars and write_lines are atomic.

For example if you use write_line in two different threads, the two operations will be serialized, and lines cannot be mixed.

val write_char : output_channel -> char -> unit Lwt.t

write_char oc char writes char on oc

val write_chars : output_channel -> char Lwt_stream.t -> unit Lwt.t

write_chars oc chars writes all characters of chars on oc

val write : output_channel -> string -> unit Lwt.t

write oc str writes all characters of str on oc

val write_line : output_channel -> string -> unit Lwt.t

write_line oc str writes str on oc followed by a new-line.

val write_lines : output_channel -> string Lwt_stream.t -> unit Lwt.t

write_lines oc lines writes all lines of lines to oc

val write_from : output_channel -> bytes -> int -> int -> int Lwt.t

write_from oc buffer offset length writes up to length bytes to oc, from buffer at offset offset and returns the number of bytes actually written

val write_from_bigstring : + output_channel -> + Lwt_bytes.t -> + int -> + int -> + int Lwt.t
val write_from_string : output_channel -> string -> int -> int -> int Lwt.t

See write.

val write_from_exactly : output_channel -> bytes -> int -> int -> unit Lwt.t

write_from_exactly oc buffer offset length writes all length bytes from buffer at offset offset to oc

val write_from_exactly_bigstring : + output_channel -> + Lwt_bytes.t -> + int -> + int -> + unit Lwt.t
val write_from_string_exactly : + output_channel -> + string -> + int -> + int -> + unit Lwt.t
val write_value : + output_channel -> + ?flags:Stdlib.Marshal.extern_flags list -> + 'a -> + unit Lwt.t

write_value channel ?flags v writes v to channel using the Marshal module of the standard library. See Stdlib.Marshal.to_channel for an explanation of ?flags.

The corresponding reading function is read_value. See warnings about type safety in the description of read_value.

Printing

These functions are basically helpers. Also you may prefer using the name printl rather than write_line because it is shorter.

The general name of a printing function is <prefix>print<suffixes>,

where <prefix> is one of:

and <suffixes> is a combination of:

val fprint : output_channel -> string -> unit Lwt.t
val fprintl : output_channel -> string -> unit Lwt.t
val fprintf : output_channel -> ('a, unit, string, unit Lwt.t) format4 -> 'a

%! does nothing here. To flush the channel, use Lwt_io.flush channel.

val fprintlf : output_channel -> ('a, unit, string, unit Lwt.t) format4 -> 'a

%! does nothing here. To flush the channel, use Lwt_io.flush channel.

val print : string -> unit Lwt.t
val printl : string -> unit Lwt.t
val printf : ('a, unit, string, unit Lwt.t) format4 -> 'a

%! does nothing here. To flush the channel, use Lwt_io.(flush stdout).

val printlf : ('a, unit, string, unit Lwt.t) format4 -> 'a

%! does nothing here. To flush the channel, use Lwt_io.(flush stdout).

val eprint : string -> unit Lwt.t
val eprintl : string -> unit Lwt.t
val eprintf : ('a, unit, string, unit Lwt.t) format4 -> 'a

%! does nothing here. To flush the channel, use Lwt_io.(flush stderr).

val eprintlf : ('a, unit, string, unit Lwt.t) format4 -> 'a

%! does nothing here. To flush the channel, use Lwt_io.(flush stderr).

Utilities

val hexdump_stream : output_channel -> char Lwt_stream.t -> unit Lwt.t

hexdump_stream oc byte_stream produces the same output as the command hexdump -C.

val hexdump : output_channel -> string -> unit Lwt.t

hexdump oc str = hexdump_stream oc (Lwt_stream.of_string str)

File utilities

type file_name = string

Type of file names

val open_file : + ?buffer:Lwt_bytes.t -> + ?flags:Unix.open_flag list -> + ?perm:Unix.file_perm -> + mode:'a mode -> + file_name -> + 'a channel Lwt.t

Lwt_io.open_file ~mode file opens the given file, either for reading (with ~mode:Input) or for writing (with ~mode:Output). The returned channel provides buffered I/O on the file.

If ~buffer is supplied, it is used as the I/O buffer.

If ~flags is supplied, the file is opened with the given flags (see Unix.open_flag). Note that ~flags is used exactly as given. For example, opening a file with ~flags and ~mode:Input does not implicitly add O_RDONLY. So, you should include O_RDONLY when opening for reading (~mode:Input), and O_WRONLY when opening for writing (~mode:Input). It is also recommended to include O_NONBLOCK, unless you are sure that the file cannot be a socket or a named pipe.

The default permissions used for creating new files are 0o666, i.e. reading and writing are allowed for the file owner, group, and everyone. These default permissions can be overridden by supplying ~perm.

Note: if opening for writing (~mode:Output), and the file already exists, open_file truncates (clears) the file by default. If you would like to keep the pre-existing contents of the file, use the ~flags parameter to pass a custom flags list that does not include Unix.open_flag.O_TRUNC.

val with_file : + ?buffer:Lwt_bytes.t -> + ?flags:Unix.open_flag list -> + ?perm:Unix.file_perm -> + mode:'a mode -> + file_name -> + ('a channel -> 'b Lwt.t) -> + 'b Lwt.t

Lwt_io.with_file ~mode filename f opens the given using Lwt_io.open_file, and passes the resulting channel to f. Lwt_io.with_file ensures that the channel is closed when the promise returned by f resolves, or if f raises an exception.

See Lwt_io.open_file for a description of the arguments, warnings, and other notes.

val open_temp_file : + ?buffer:Lwt_bytes.t -> + ?flags:Unix.open_flag list -> + ?perm:Unix.file_perm -> + ?temp_dir:string -> + ?prefix:string -> + ?suffix:string -> + unit -> + (string * output_channel) Lwt.t

open_temp_file () starts creating a new temporary file, and evaluates to a promise for the pair of the file's name, and an output channel for writing to the file.

The caller should take care to delete the file later. Alternatively, see Lwt_io.with_temp_file.

The ?buffer and ?perm arguments are passed directly to an internal call to Lwt_io.open_file.

If not specified, ?flags defaults to [O_CREATE; O_EXCL; O_WRONLY; O_CLOEXEC]. If specified, the specified flags are used exactly. Note that these should typically contain at least O_CREAT and O_EXCL, otherwise open_temp_file may open an existing file.

?temp_dir can be used to choose the directory in which the file is created. For the current directory, use Stdlib.Filename.current_dir_name. If not specified, the directory is taken from Stdlib.Filename.get_temp_dir_name, which is typically set to your system temporary file directory.

?prefix helps determine the name of the file. It will be the prefix concatenated with a random sequence of characters. If not specified, open_temp_file uses some default prefix.

?suffix is like prefix, but it is appended at the end of the filename. In particular, it can be used to set the extension. This argument is supported since Lwt 4.4.0.

  • since 3.2.0
val with_temp_file : + ?buffer:Lwt_bytes.t -> + ?flags:Unix.open_flag list -> + ?perm:Unix.file_perm -> + ?temp_dir:string -> + ?prefix:string -> + ?suffix:string -> + ((string * output_channel) -> 'b Lwt.t) -> + 'b Lwt.t

with_temp_file f calls open_temp_file (), passing all optional arguments directly to it. It then attaches f to run after the file is created, passing the filename and output channel to f. When the promise returned by f is resolved, with_temp_file closes the channel and deletes the temporary file by calling Lwt_unix.unlink.

  • since 3.2.0
val create_temp_dir : + ?perm:Unix.file_perm -> + ?parent:string -> + ?prefix:string -> + ?suffix:string -> + unit -> + string Lwt.t

Creates a temporary directory, and returns a promise that resolves to its path. The caller must take care to remove the directory. Alternatively, see Lwt_io.with_temp_dir.

If ~perm is specified, the directory is created with the given permissions. The default permissions are 0755.

~parent is the directory in which the temporary directory is created. If not specified, the default value is the result of Filename.get_temp_dir_name ().

~prefix is prepended to the directory name, and ~suffix is appended to it.

  • since 4.4.0
val with_temp_dir : + ?perm:Unix.file_perm -> + ?parent:string -> + ?prefix:string -> + ?suffix:string -> + (string -> 'a Lwt.t) -> + 'a Lwt.t

with_temp_dir f first calls create_temp_dir, forwarding all optional arguments to it. Once the temporary directory is created at path, with_temp_dir f calls f path. When the promise returned by f path is resolved, with_temp_dir f recursively deletes the temporary directory and all its contents by calling Lwt_io.delete_recursively.

  • since 4.4.0
val delete_recursively : string -> unit Lwt.t

delete_recursively path attempts to delete the directory path and all its content recursively.

This is likely VERY slow for directories with many files. That is probably best addressed by switching to blocking calls run inside a worker thread, i.e. with Lwt_preemptive.

  • since 5.7.0
val open_connection : + ?fd:Lwt_unix.file_descr -> + ?in_buffer:Lwt_bytes.t -> + ?out_buffer:Lwt_bytes.t -> + Unix.sockaddr -> + (input_channel * output_channel) Lwt.t

open_connection ?fd ?in_buffer ?out_buffer addr opens a connection to the given address and returns two channels for using it. If fd is not specified, a fresh one will be used.

The connection is completely closed when you close both channels.

val with_connection : + ?fd:Lwt_unix.file_descr -> + ?in_buffer:Lwt_bytes.t -> + ?out_buffer:Lwt_bytes.t -> + Unix.sockaddr -> + ((input_channel * output_channel) -> 'a Lwt.t) -> + 'a Lwt.t

with_connection ?fd ?in_buffer ?out_buffer addr f opens a connection to the given address and passes the channels to f

type server

Type of a server

val establish_server_with_client_socket : + ?server_fd:Lwt_unix.file_descr -> + ?backlog:int -> + ?no_close:bool -> + Unix.sockaddr -> + (Lwt_unix.sockaddr -> Lwt_unix.file_descr -> unit Lwt.t) -> + server Lwt.t

establish_server_with_client_socket listen_address f creates a server which listens for incoming connections on listen_address. When a client makes a new connection, it is passed to f: more precisely, the server calls

f client_address client_socket

where client_address is the address (peer name) of the new client, and client_socket is the socket connected to the client.

The server does not block waiting for f to complete: it concurrently tries to accept more client connections while f is handling the client.

When the promise returned by f completes (i.e., f is done handling the client), establish_server_with_client_socket automatically closes client_socket. This is a default behavior that is useful for simple cases, but for a robust application you should explicitly close these channels yourself, and handle any exceptions as appropriate. If the channels are still open when f completes, and their automatic closing raises an exception, establish_server_with_client_socket treats it as an unhandled exception reaching the top level of the application: it passes that exception to Lwt.async_exception_hook, the default behavior of which is to print the exception and terminate your process.

Automatic closing can be completely disabled by passing ~no_close:true.

Similarly, if f raises an exception (or the promise it returns fails with an exception), establish_server_with_client_socket can do nothing with that exception, except pass it to Lwt.async_exception_hook.

~server_fd can be specified to use an existing file descriptor for listening. Otherwise, a fresh socket is created internally. In either case, establish_server_with_client_socket will internally assign listen_address to the server socket.

~backlog is the argument passed to Lwt_unix.listen. Its default value is SOMAXCONN, which varies by platform and socket kind.

The returned promise (a server Lwt.t) resolves when the server has just started listening on listen_address: right after the internal call to listen, and right before the first internal call to accept.

  • since 4.1.0
val establish_server_with_client_address : + ?fd:Lwt_unix.file_descr -> + ?buffer_size:int -> + ?backlog:int -> + ?no_close:bool -> + Unix.sockaddr -> + (Lwt_unix.sockaddr -> (input_channel * output_channel) -> unit Lwt.t) -> + server Lwt.t

Like Lwt_io.establish_server_with_client_socket, but passes two buffered channels to the connection handler f. These channels wrap the client socket.

The channels are closed automatically when the promise returned by f resolves. To avoid this behavior, pass ~no_close:true.

  • since 3.1.0
val shutdown_server : server -> unit Lwt.t

Closes the given server's listening socket. The returned promise resolves when the close(2) system call completes. This function does not affect the sockets of connections that have already been accepted, i.e. passed to f by establish_server.

  • since 3.0.0
val lines_of_file : file_name -> string Lwt_stream.t

lines_of_file name returns a stream of all lines of the file with name name. The file is automatically closed when all lines have been read.

val lines_to_file : file_name -> string Lwt_stream.t -> unit Lwt.t

lines_to_file name lines writes all lines of lines to file with name name.

val chars_of_file : file_name -> char Lwt_stream.t

chars_of_file name returns a stream of all characters of the file with name name. As for lines_of_file the file is closed when all characters have been read.

val chars_to_file : file_name -> char Lwt_stream.t -> unit Lwt.t

chars_to_file name chars writes all characters of chars to name

Input/output of integers

module type NumberIO = sig ... end

Common interface for reading/writing integers in binary

module LE : NumberIO

Reading/writing of numbers in little-endian

module BE : NumberIO

Reading/writing of numbers in big-endian

Reading/writing of numbers in the system endianness.

include NumberIO

Reading

val read_int : input_channel -> int Lwt.t

Reads a 32-bits integer as an ocaml int

val read_int16 : input_channel -> int Lwt.t
val read_int32 : input_channel -> int32 Lwt.t
val read_int64 : input_channel -> int64 Lwt.t
val read_float32 : input_channel -> float Lwt.t

Reads an IEEE single precision floating point value

val read_float64 : input_channel -> float Lwt.t

Reads an IEEE double precision floating point value

Writing

val write_int : output_channel -> int -> unit Lwt.t

Writes an ocaml int as a 32-bits integer

val write_int16 : output_channel -> int -> unit Lwt.t
val write_int32 : output_channel -> int32 -> unit Lwt.t
val write_int64 : output_channel -> int64 -> unit Lwt.t
val write_float32 : output_channel -> float -> unit Lwt.t

Writes an IEEE single precision floating point value

val write_float64 : output_channel -> float -> unit Lwt.t

Writes an IEEE double precision floating point value

type byte_order = Lwt_sys.byte_order =
  1. | Little_endian
  2. | Big_endian
    (*

    Type of byte order

    *)
val system_byte_order : byte_order

Low-level access to the internal buffer

val block : 'a channel -> int -> (Lwt_bytes.t -> int -> 'b Lwt.t) -> 'b Lwt.t

block ch size f pass to f the internal buffer and an offset. The buffer contains size chars at offset. f may read or write these chars. size must satisfy 0 <= size <= 16

type direct_access = {
  1. da_buffer : Lwt_bytes.t;
    (*

    The internal buffer

    *)
  2. mutable da_ptr : int;
    (*

    The pointer to:

    • the beginning of free space for output channels
    • the beginning of data for input channels
    *)
  3. mutable da_max : int;
    (*

    The maximum offset

    *)
  4. da_perform : unit -> int Lwt.t;
    (*
    • for input channels: refills the buffer and returns how many bytes have been read
    • for output channels: flush partially the buffer and returns how many bytes have been written
    *)
}

Information for directly accessing the internal buffer of a channel

val direct_access : 'a channel -> (direct_access -> 'b Lwt.t) -> 'b Lwt.t

direct_access ch f passes to f a direct_access structure. f must use it and update da_ptr to reflect how many bytes have been read/written.

Misc

val default_buffer_size : unit -> int

Return the default size for buffers. Channels that are created without a specific buffer use new buffer of this size.

val set_default_buffer_size : int -> unit

Change the default buffer size.

Deprecated

val establish_server : + ?fd:Lwt_unix.file_descr -> + ?buffer_size:int -> + ?backlog:int -> + ?no_close:bool -> + Unix.sockaddr -> + ((input_channel * output_channel) -> unit Lwt.t) -> + server Lwt.t

Like establish_server_with_client_address, but does not pass the client address or fd to the callback f.

  • since 3.0.0
module Versioned : sig ... end

Versioned variants of APIs undergoing breaking changes.

diff --git a/dev/lwt/Lwt_io/module-type-NumberIO/index.html b/dev/lwt/Lwt_io/module-type-NumberIO/index.html new file mode 100644 index 00000000..f73f13a0 --- /dev/null +++ b/dev/lwt/Lwt_io/module-type-NumberIO/index.html @@ -0,0 +1,2 @@ + +NumberIO (lwt.Lwt_io.NumberIO)

Module type Lwt_io.NumberIO

Common interface for reading/writing integers in binary

Reading

val read_int : input_channel -> int Lwt.t

Reads a 32-bits integer as an ocaml int

val read_int16 : input_channel -> int Lwt.t
val read_int32 : input_channel -> int32 Lwt.t
val read_int64 : input_channel -> int64 Lwt.t
val read_float32 : input_channel -> float Lwt.t

Reads an IEEE single precision floating point value

val read_float64 : input_channel -> float Lwt.t

Reads an IEEE double precision floating point value

Writing

val write_int : output_channel -> int -> unit Lwt.t

Writes an ocaml int as a 32-bits integer

val write_int16 : output_channel -> int -> unit Lwt.t
val write_int32 : output_channel -> int32 -> unit Lwt.t
val write_int64 : output_channel -> int64 -> unit Lwt.t
val write_float32 : output_channel -> float -> unit Lwt.t

Writes an IEEE single precision floating point value

val write_float64 : output_channel -> float -> unit Lwt.t

Writes an IEEE double precision floating point value

diff --git a/dev/lwt/Lwt_list/index.html b/dev/lwt/Lwt_list/index.html new file mode 100644 index 00000000..02a7fcc9 --- /dev/null +++ b/dev/lwt/Lwt_list/index.html @@ -0,0 +1,2 @@ + +Lwt_list (lwt.Lwt_list)

Module Lwt_list

List helpers

Note: this module use the same naming convention as Lwt_stream.

List iterators

val iter_s : ('a -> unit Lwt.t) -> 'a list -> unit Lwt.t
val iter_p : ('a -> unit Lwt.t) -> 'a list -> unit Lwt.t
val iteri_s : (int -> 'a -> unit Lwt.t) -> 'a list -> unit Lwt.t
val iteri_p : (int -> 'a -> unit Lwt.t) -> 'a list -> unit Lwt.t
val map_s : ('a -> 'b Lwt.t) -> 'a list -> 'b list Lwt.t
val map_p : ('a -> 'b Lwt.t) -> 'a list -> 'b list Lwt.t
val mapi_s : (int -> 'a -> 'b Lwt.t) -> 'a list -> 'b list Lwt.t
val mapi_p : (int -> 'a -> 'b Lwt.t) -> 'a list -> 'b list Lwt.t
val rev_map_s : ('a -> 'b Lwt.t) -> 'a list -> 'b list Lwt.t
val rev_map_p : ('a -> 'b Lwt.t) -> 'a list -> 'b list Lwt.t
val fold_left_s : ('a -> 'b -> 'a Lwt.t) -> 'a -> 'b list -> 'a Lwt.t
val fold_right_s : ('a -> 'b -> 'b Lwt.t) -> 'a list -> 'b -> 'b Lwt.t

List scanning

val for_all_s : ('a -> bool Lwt.t) -> 'a list -> bool Lwt.t
val for_all_p : ('a -> bool Lwt.t) -> 'a list -> bool Lwt.t
val exists_s : ('a -> bool Lwt.t) -> 'a list -> bool Lwt.t
val exists_p : ('a -> bool Lwt.t) -> 'a list -> bool Lwt.t

List searching

val find_s : ('a -> bool Lwt.t) -> 'a list -> 'a Lwt.t
val filter_s : ('a -> bool Lwt.t) -> 'a list -> 'a list Lwt.t
val filter_p : ('a -> bool Lwt.t) -> 'a list -> 'a list Lwt.t
val filter_map_s : ('a -> 'b option Lwt.t) -> 'a list -> 'b list Lwt.t
val filter_map_p : ('a -> 'b option Lwt.t) -> 'a list -> 'b list Lwt.t
val partition_s : ('a -> bool Lwt.t) -> 'a list -> ('a list * 'a list) Lwt.t
val partition_p : ('a -> bool Lwt.t) -> 'a list -> ('a list * 'a list) Lwt.t
diff --git a/dev/lwt/Lwt_main/Enter_iter_hooks/index.html b/dev/lwt/Lwt_main/Enter_iter_hooks/index.html new file mode 100644 index 00000000..4ec259a4 --- /dev/null +++ b/dev/lwt/Lwt_main/Enter_iter_hooks/index.html @@ -0,0 +1,2 @@ + +Enter_iter_hooks (lwt.Lwt_main.Enter_iter_hooks)

Module Lwt_main.Enter_iter_hooks

Hooks, of type unit -> unit, that are called before each iteration of the Lwt main loop.

type 'return_value kind = 'return_value

Hooks are functions of either type unit -> unit or unit -> unit Lwt.t; this type constructor is used only to express both possibilities in one signature.

type hook

Values of type hook represent hooks that have been added, so that they can be removed later (if needed).

val add_first : (unit -> unit kind) -> hook

Adds a hook to the hook sequence underlying this module, to be run first, before any other hooks already added.

val add_last : (unit -> unit kind) -> hook

Adds a hook to the hook sequence underlying this module, to be run last, after any other hooks already added.

val remove : hook -> unit

Removes a hook added by add_first or add_last.

val remove_all : unit -> unit

Removes all hooks from the hook sequence underlying this module.

diff --git a/dev/lwt/Lwt_main/Exit_hooks/index.html b/dev/lwt/Lwt_main/Exit_hooks/index.html new file mode 100644 index 00000000..ed8db270 --- /dev/null +++ b/dev/lwt/Lwt_main/Exit_hooks/index.html @@ -0,0 +1,2 @@ + +Exit_hooks (lwt.Lwt_main.Exit_hooks)

Module Lwt_main.Exit_hooks

Promise-returning hooks, of type unit -> unit Lwt.t, that are called at process exit. Exceptions raised by these hooks are ignored.

type 'return_value kind = 'return_value Lwt.t

Hooks are functions of either type unit -> unit or unit -> unit Lwt.t; this type constructor is used only to express both possibilities in one signature.

type hook

Values of type hook represent hooks that have been added, so that they can be removed later (if needed).

val add_first : (unit -> unit kind) -> hook

Adds a hook to the hook sequence underlying this module, to be run first, before any other hooks already added.

val add_last : (unit -> unit kind) -> hook

Adds a hook to the hook sequence underlying this module, to be run last, after any other hooks already added.

val remove : hook -> unit

Removes a hook added by add_first or add_last.

val remove_all : unit -> unit

Removes all hooks from the hook sequence underlying this module.

diff --git a/dev/lwt/Lwt_main/Leave_iter_hooks/index.html b/dev/lwt/Lwt_main/Leave_iter_hooks/index.html new file mode 100644 index 00000000..2752ed39 --- /dev/null +++ b/dev/lwt/Lwt_main/Leave_iter_hooks/index.html @@ -0,0 +1,2 @@ + +Leave_iter_hooks (lwt.Lwt_main.Leave_iter_hooks)

Module Lwt_main.Leave_iter_hooks

Hooks, of type unit -> unit, that are called after each iteration of the Lwt main loop.

type 'return_value kind = 'return_value

Hooks are functions of either type unit -> unit or unit -> unit Lwt.t; this type constructor is used only to express both possibilities in one signature.

type hook

Values of type hook represent hooks that have been added, so that they can be removed later (if needed).

val add_first : (unit -> unit kind) -> hook

Adds a hook to the hook sequence underlying this module, to be run first, before any other hooks already added.

val add_last : (unit -> unit kind) -> hook

Adds a hook to the hook sequence underlying this module, to be run last, after any other hooks already added.

val remove : hook -> unit

Removes a hook added by add_first or add_last.

val remove_all : unit -> unit

Removes all hooks from the hook sequence underlying this module.

diff --git a/dev/lwt/Lwt_main/index.html b/dev/lwt/Lwt_main/index.html new file mode 100644 index 00000000..ab034748 --- /dev/null +++ b/dev/lwt/Lwt_main/index.html @@ -0,0 +1,4 @@ + +Lwt_main (lwt.Lwt_main)

Module Lwt_main

Main loop and event queue

This module controls the ``main-loop'' of Lwt.

val run : 'a Lwt.t -> 'a

Lwt_main.run p calls the Lwt scheduler, performing I/O until p resolves. Lwt_main.run p returns the value in p if p is fulfilled. If p is rejected with an exception instead, Lwt_main.run p raises that exception.

Every native and bytecode program that uses Lwt should call this function at its top level. It implements the Lwt main loop.

Example:

let main () = Lwt_io.write_line Lwt_io.stdout "hello world"
+
+let () = Lwt_main.run (main ())

Lwt_main.run is not available when targeting JavaScript, because the environment (such as Node.js or the browser's script engine) implements the I/O loop.

On Unix, calling Lwt_main.run installs a SIGCHLD handler, which is needed for the implementations of Lwt_unix.waitpid and Lwt_unix.wait4. As a result, programs that call Lwt_main.run and also use non-Lwt system calls need to handle those system calls failing with EINTR.

Nested calls to Lwt_main.run are not allowed. That is, do not call Lwt_main.run in a callback triggered by a promise that is resolved by an outer invocation of Lwt_main.run. If your program makes such a call, Lwt_main.run will raise Failure. This should be considered a logic error (i.e., code making such a call is inherently broken).

In addition, note that if you have set the exception filter to let runtime exceptions bubble up (via Lwt.Exception_filter.(set handle_all_except_runtime)) then Lwt does not attempt to catch exceptions thrown by the OCaml runtime. Specifically, in this case, Lwt lets Out_of_memory and Stack_overflow exceptions traverse all of its functions and bubble up to the caller of Lwt_main.run. Moreover because these exceptions are left to traverse the call stack, they leave the internal data-structures in an inconsistent state. For this reason, calling Lwt_main.run again after such an exception will raise Failure.

It is not safe to call Lwt_main.run in a function registered with Stdlib.at_exit, use Lwt_main.at_exit instead.

val yield : unit -> unit Lwt.t

yield () is a pending promise that is fulfilled after Lwt finishes calling all currently ready callbacks, i.e. it is fulfilled on the next β€œtick.”

  • deprecated

    Since 5.5.0 yield is deprecated in favor of the more general Lwt.pause in order to avoid discrepancies in resolution (see below) and stay compatible with other execution environments such as js_of_ocaml.

val abandon_yielded_and_paused : unit -> unit

Causes promises created with Lwt.pause and Lwt_main.yield to remain forever pending.

(Note that yield is deprecated in favor of the more general Lwt.pause.)

This is meant for use with Lwt_unix.fork, as a way to β€œabandon” more promise chains that are pending in your process.

  • deprecated

    Since 5.7 abandon_yielded_and_paused is deprecated in favour of Lwt.abandon_paused.

module type Hooks = sig ... end

Hook sequences. Each module of this type is a set of hooks, to be run by Lwt at certain points during execution. See modules Enter_iter_hooks, Leave_iter_hooks, and Exit_hooks.

module Enter_iter_hooks : Hooks with type 'return_value kind = 'return_value

Hooks, of type unit -> unit, that are called before each iteration of the Lwt main loop.

module Leave_iter_hooks : Hooks with type 'return_value kind = 'return_value

Hooks, of type unit -> unit, that are called after each iteration of the Lwt main loop.

module Exit_hooks : Hooks with type 'return_value kind = 'return_value Lwt.t

Promise-returning hooks, of type unit -> unit Lwt.t, that are called at process exit. Exceptions raised by these hooks are ignored.

val enter_iter_hooks : (unit -> unit) Lwt_sequence.t
val leave_iter_hooks : (unit -> unit) Lwt_sequence.t
val exit_hooks : (unit -> unit Lwt.t) Lwt_sequence.t
val at_exit : (unit -> unit Lwt.t) -> unit

Lwt_main.at_exit hook is the same as ignore (Lwt_main.Exit_hooks.add_first hook).

diff --git a/dev/lwt/Lwt_main/module-type-Hooks/index.html b/dev/lwt/Lwt_main/module-type-Hooks/index.html new file mode 100644 index 00000000..fba84125 --- /dev/null +++ b/dev/lwt/Lwt_main/module-type-Hooks/index.html @@ -0,0 +1,2 @@ + +Hooks (lwt.Lwt_main.Hooks)

Module type Lwt_main.Hooks

Hook sequences. Each module of this type is a set of hooks, to be run by Lwt at certain points during execution. See modules Enter_iter_hooks, Leave_iter_hooks, and Exit_hooks.

type 'return_value kind

Hooks are functions of either type unit -> unit or unit -> unit Lwt.t; this type constructor is used only to express both possibilities in one signature.

type hook

Values of type hook represent hooks that have been added, so that they can be removed later (if needed).

val add_first : (unit -> unit kind) -> hook

Adds a hook to the hook sequence underlying this module, to be run first, before any other hooks already added.

val add_last : (unit -> unit kind) -> hook

Adds a hook to the hook sequence underlying this module, to be run last, after any other hooks already added.

val remove : hook -> unit

Removes a hook added by add_first or add_last.

val remove_all : unit -> unit

Removes all hooks from the hook sequence underlying this module.

diff --git a/dev/lwt/Lwt_mutex/index.html b/dev/lwt/Lwt_mutex/index.html new file mode 100644 index 00000000..a35e7929 --- /dev/null +++ b/dev/lwt/Lwt_mutex/index.html @@ -0,0 +1,2 @@ + +Lwt_mutex (lwt.Lwt_mutex)

Module Lwt_mutex

Cooperative locks for mutual exclusion

type t

Type of Lwt mutexes

val create : unit -> t

create () creates a new mutex, which is initially unlocked

val lock : t -> unit Lwt.t

lock mutex lockcs the mutex, that is:

  • if the mutex is unlocked, then it is marked as locked and lock returns immediately
  • if it is locked, then lock waits for all threads waiting on the mutex to terminate, then it resumes when the last one unlocks the mutex

Note: threads are woken up in the same order they try to lock the mutex

val unlock : t -> unit

unlock mutex unlock the mutex if no threads is waiting on it. Otherwise it will eventually removes the first one and resumes it.

val is_locked : t -> bool

locked mutex returns whether mutex is currently locked

val is_empty : t -> bool

is_empty mutex returns true if they are no thread waiting on the mutex, and false otherwise

val with_lock : t -> (unit -> 'a Lwt.t) -> 'a Lwt.t

with_lock lock f is used to lock a mutex within a block scope. The function f () is called with the mutex locked, and its result is returned from the call to with_lock. If an exception is raised from f, the mutex is also unlocked before the scope of with_lock is exited.

diff --git a/dev/lwt/Lwt_mvar/index.html b/dev/lwt/Lwt_mvar/index.html new file mode 100644 index 00000000..fd5a3dbc --- /dev/null +++ b/dev/lwt/Lwt_mvar/index.html @@ -0,0 +1,2 @@ + +Lwt_mvar (lwt.Lwt_mvar)

Module Lwt_mvar

Mailbox variables

β€œMailbox” variables implement a synchronising variable, used for communication between concurrent threads.

type 'a t

The type of a mailbox variable. Mailbox variables are used to communicate values between threads in a synchronous way. The type parameter specifies the type of the value propagated from put to take.

val create : 'a -> 'a t

create v creates a new mailbox variable containing value v.

val create_empty : unit -> 'a t

create () creates a new empty mailbox variable.

val put : 'a t -> 'a -> unit Lwt.t

put mvar value puts a value into a mailbox variable. This value will remain in the mailbox until take is called to remove it. If the mailbox is not empty, the current thread will block until it is emptied.

val take : 'a t -> 'a Lwt.t

take mvar will take any currently available value from the mailbox variable. If no value is currently available, the current thread will block, awaiting a value to be put by another thread.

val take_available : 'a t -> 'a option

take_available mvar immediately takes the value from mvar without blocking, returning None if the mailbox is empty.

  • since 3.2.0
val is_empty : 'a t -> bool

is_empty mvar indicates if put mvar can be called without blocking.

  • since 3.2.0
diff --git a/dev/lwt/Lwt_pool/index.html b/dev/lwt/Lwt_pool/index.html new file mode 100644 index 00000000..a06f798e --- /dev/null +++ b/dev/lwt/Lwt_pool/index.html @@ -0,0 +1,22 @@ + +Lwt_pool (lwt.Lwt_pool)

Module Lwt_pool

External resource pools.

This module provides an abstraction for managing collections of resources. One example use case is for managing a pool of database connections, where instead of establishing a new connection each time you need one (which is expensive), you can keep a pool of opened connections and reuse ones that are free.

It also provides the capability of:

The following example illustrates how it is used with an imaginary Db module:

let uri = "postgresql://localhost:5432"
+
+(* Create a database connection pool with max size of 10. *)
+let pool =
+  Lwt_pool.create 10
+    ~dispose:(fun connection -> Db.close connection |> Lwt.return)
+    (fun () -> Db.connect uri |> Lwt.return)
+
+(* Use the pool in queries. *)
+let create_user name =
+  Lwt_pool.use pool (fun connection ->
+      connection
+      |> Db.insert "users" [("name", name)]
+      |> Lwt.return
+    )

Note that this is not intended to keep a pool of system threads. If you want to have such pool, consider using Lwt_preemptive.

type 'a t

A pool containing elements of type 'a.

val create : + int -> + ?validate:('a -> bool Lwt.t) -> + ?check:('a -> (bool -> unit) -> unit) -> + ?dispose:('a -> unit Lwt.t) -> + (unit -> 'a Lwt.t) -> + 'a t

create n ?check ?validate ?dispose f creates a new pool with at most n elements. f is used to create a new pool element. Elements are created on demand and re-used until disposed of.

  • parameter validate

    is called each time a pool element is accessed by use, before the element is provided to use's callback. If validate element resolves to true the element is considered valid and is passed to the callback for use as-is. If validate element resolves to false the tested pool element is passed to dispose then dropped, with a new one is created to take element's place in the pool. validate is available since Lwt 3.2.0.

  • parameter check

    is called after the resolution of use's callback when the resolution is a failed promise. check element is_ok must call is_ok exactly once with true if element is still valid and false otherwise. If check calls is_ok false then dispose will be run on element and the element will not be returned to the pool.

  • parameter dispose

    is used as described above and by clear to dispose of all elements in a pool. dispose is not guaranteed to be called on the elements in a pool when the pool is garbage collected. clear should be used if the elements of the pool need to be explicitly disposed of.

val use : 'a t -> ('a -> 'b Lwt.t) -> 'b Lwt.t

use p f requests one free element of the pool p and gives it to the function f. The element is put back into the pool after the promise created by f completes.

In the case that p is exhausted and the maximum number of elements is reached, use will wait until one becomes free.

val clear : 'a t -> unit Lwt.t

clear p will clear all elements in p, calling the dispose function associated with p on each of the cleared elements. Any elements from p which are currently in use will be disposed of once they are released.

The next call to use p after clear p guarantees a freshly created pool element.

Disposals are performed sequentially in an undefined order.

  • since 3.2.0
val wait_queue_length : _ t -> int

wait_queue_length p returns the number of use requests currently waiting for an element of the pool p to become available.

  • since 3.2.0
diff --git a/dev/lwt/Lwt_pqueue/Make/argument-1-Ord/index.html b/dev/lwt/Lwt_pqueue/Make/argument-1-Ord/index.html new file mode 100644 index 00000000..d95765cf --- /dev/null +++ b/dev/lwt/Lwt_pqueue/Make/argument-1-Ord/index.html @@ -0,0 +1,2 @@ + +Ord (lwt.Lwt_pqueue.Make.Ord)

Parameter Make.Ord

type t
val compare : t -> t -> int
diff --git a/dev/lwt/Lwt_pqueue/Make/index.html b/dev/lwt/Lwt_pqueue/Make/index.html new file mode 100644 index 00000000..f357de5a --- /dev/null +++ b/dev/lwt/Lwt_pqueue/Make/index.html @@ -0,0 +1,2 @@ + +Make (lwt.Lwt_pqueue.Make)

Module Lwt_pqueue.Make

Generates priority queue types from ordered types.

Parameters

module Ord : OrderedType

Signature

type elt = Ord.t

Type of elements contained in the priority queue.

type t

Type of priority queues.

val empty : t

The empty priority queue. Contains no elements.

val is_empty : t -> bool

is_empty q evaluates to true iff q is empty.

val add : elt -> t -> t

add e q evaluates to a new priority queue, which contains all the elements of q, and the additional element e.

val union : t -> t -> t

union q q' evaluates to a new priority queue, which contains all the elements of both q and q'.

val find_min : t -> elt

find_min q evaluates to the minimum element of q if it is not empty, and raises Not_found otherwise.

val lookup_min : t -> elt option

lookup_min q evaluates to Some e, where e is the minimum element of q, if q is not empty, and evaluates to None otherwise.

val remove_min : t -> t

remove_min q evaluates to a new priority queue, which contains all the elements of q except for its minimum element. Raises Not_found if q is empty.

val size : t -> int

size q evaluates to the number of elements in q.

diff --git a/dev/lwt/Lwt_pqueue/index.html b/dev/lwt/Lwt_pqueue/index.html new file mode 100644 index 00000000..2ba21607 --- /dev/null +++ b/dev/lwt/Lwt_pqueue/index.html @@ -0,0 +1,2 @@ + +Lwt_pqueue (lwt.Lwt_pqueue)

Module Lwt_pqueue

Functional priority queues (deprecated).

A priority queue maintains, in the abstract sense, a set of elements in order, and supports fast lookup and removal of the first (β€œminimum”) element. This is used in Lwt for organizing threads that are waiting for timeouts.

The priority queues in this module preserve β€œduplicates”: elements that compare equal in their order.

module type OrderedType = sig ... end

Signature pairing an element type with an ordering function.

module type S = sig ... end

Signature of priority queues.

module Make (Ord : OrderedType) : S with type elt = Ord.t

Generates priority queue types from ordered types.

diff --git a/dev/lwt/Lwt_pqueue/module-type-OrderedType/index.html b/dev/lwt/Lwt_pqueue/module-type-OrderedType/index.html new file mode 100644 index 00000000..c3dcfbb7 --- /dev/null +++ b/dev/lwt/Lwt_pqueue/module-type-OrderedType/index.html @@ -0,0 +1,2 @@ + +OrderedType (lwt.Lwt_pqueue.OrderedType)

Module type Lwt_pqueue.OrderedType

Signature pairing an element type with an ordering function.

type t
val compare : t -> t -> int
diff --git a/dev/lwt/Lwt_pqueue/module-type-S/index.html b/dev/lwt/Lwt_pqueue/module-type-S/index.html new file mode 100644 index 00000000..8669020c --- /dev/null +++ b/dev/lwt/Lwt_pqueue/module-type-S/index.html @@ -0,0 +1,2 @@ + +S (lwt.Lwt_pqueue.S)

Module type Lwt_pqueue.S

Signature of priority queues.

type elt

Type of elements contained in the priority queue.

type t

Type of priority queues.

val empty : t

The empty priority queue. Contains no elements.

val is_empty : t -> bool

is_empty q evaluates to true iff q is empty.

val add : elt -> t -> t

add e q evaluates to a new priority queue, which contains all the elements of q, and the additional element e.

val union : t -> t -> t

union q q' evaluates to a new priority queue, which contains all the elements of both q and q'.

val find_min : t -> elt

find_min q evaluates to the minimum element of q if it is not empty, and raises Not_found otherwise.

val lookup_min : t -> elt option

lookup_min q evaluates to Some e, where e is the minimum element of q, if q is not empty, and evaluates to None otherwise.

val remove_min : t -> t

remove_min q evaluates to a new priority queue, which contains all the elements of q except for its minimum element. Raises Not_found if q is empty.

val size : t -> int

size q evaluates to the number of elements in q.

diff --git a/dev/lwt/Lwt_preemptive/index.html b/dev/lwt/Lwt_preemptive/index.html new file mode 100644 index 00000000..0e43aad7 --- /dev/null +++ b/dev/lwt/Lwt_preemptive/index.html @@ -0,0 +1,2 @@ + +Lwt_preemptive (lwt.Lwt_preemptive)

Module Lwt_preemptive

This module allows to mix preemptive threads with Lwt cooperative threads. It maintains an extensible pool of preemptive threads to which you can detach computations.

See Mwt for a more modern implementation.

val detach : ('a -> 'b) -> 'a -> 'b Lwt.t

detach f x runs the computation f x in a separate preemptive thread. detach evaluates to an Lwt promise, which is pending until the preemptive thread completes.

detach calls simple_init internally, which means that the number of preemptive threads is capped by default at four. If you would like a higher limit, call init or set_bounds directly.

Note that Lwt thread-local storage (i.e., Lwt.with_value) cannot be safely used from within f. The same goes for most of the rest of Lwt. If you need to run an Lwt thread in f, use run_in_main.

val run_in_main : (unit -> 'a Lwt.t) -> 'a

run_in_main f can be called from a detached computation to execute f () in the main preemptive thread, i.e. the one executing Lwt_main.run. run_in_main f blocks until f () completes, then returns its result. If f () raises an exception, run_in_main f raises the same exception.

Lwt.with_value may be used inside f (). Lwt.get can correctly retrieve values set this way inside f (), but not values set using Lwt.with_value outside f ().

val run_in_main_dont_wait : (unit -> unit Lwt.t) -> (exn -> unit) -> unit

run_in_main_dont_wait f h does the same as run_in_main f but a bit faster and lighter as it does not wait for the result of f.

If f's promise is rejected (or if it raises), then the function h is called with the rejection exception.

  • since 5.7.0
val init : int -> int -> (string -> unit) -> unit

init min max log initialises this module. i.e. it launches the minimum number of preemptive threads and starts the dispatcher.

  • parameter min

    is the minimum number of threads

  • parameter max

    is the maximum number of threads

  • parameter log

    is used to log error messages

    If Lwt_preemptive has already been initialised, this call only modify bounds and the log function.

val simple_init : unit -> unit

simple_init () checks if the library is not yet initialized, and if not, does a simple initialization. The minimum number of threads is set to zero, maximum to four, and the log function is left unchanged, i.e. the default built-in logging function is used. See Lwt_preemptive.init.

Note: this function is automatically called by detach.

val get_bounds : unit -> int * int

get_bounds () returns the minimum and the maximum number of preemptive threads.

val set_bounds : (int * int) -> unit

set_bounds (min, max) set the minimum and the maximum number of preemptive threads.

val set_max_number_of_threads_queued : int -> unit

Sets the size of the waiting queue, if no more preemptive threads are available. When the queue is full, detach will sleep until a thread is available.

val get_max_number_of_threads_queued : unit -> int

Returns the size of the waiting queue, if no more threads are available

diff --git a/dev/lwt/Lwt_process/class-process/index.html b/dev/lwt/Lwt_process/class-process/index.html new file mode 100644 index 00000000..c557f9d0 --- /dev/null +++ b/dev/lwt/Lwt_process/class-process/index.html @@ -0,0 +1,2 @@ + +process (lwt.Lwt_process.process)

Class Lwt_process.process

inherit process_none
method stdin : Lwt_io.output_channel
method stdout : Lwt_io.input_channel
diff --git a/dev/lwt/Lwt_process/class-process_full/index.html b/dev/lwt/Lwt_process/class-process_full/index.html new file mode 100644 index 00000000..c88f54e5 --- /dev/null +++ b/dev/lwt/Lwt_process/class-process_full/index.html @@ -0,0 +1,2 @@ + +process_full (lwt.Lwt_process.process_full)

Class Lwt_process.process_full

inherit process_none
method stdin : Lwt_io.output_channel
method stdout : Lwt_io.input_channel
method stderr : Lwt_io.input_channel
diff --git a/dev/lwt/Lwt_process/class-process_in/index.html b/dev/lwt/Lwt_process/class-process_in/index.html new file mode 100644 index 00000000..c0725542 --- /dev/null +++ b/dev/lwt/Lwt_process/class-process_in/index.html @@ -0,0 +1,2 @@ + +process_in (lwt.Lwt_process.process_in)

Class Lwt_process.process_in

inherit process_none
method stdout : Lwt_io.input_channel

The standard output of the process

diff --git a/dev/lwt/Lwt_process/class-process_none/index.html b/dev/lwt/Lwt_process/class-process_none/index.html new file mode 100644 index 00000000..a17d9bb4 --- /dev/null +++ b/dev/lwt/Lwt_process/class-process_none/index.html @@ -0,0 +1,2 @@ + +process_none (lwt.Lwt_process.process_none)

Class Lwt_process.process_none

method pid : int

Pid of the sub-process

method state : state

Return the state of the process

method kill : int -> unit

kill signum sends signum to the process if it is still running.

method terminate : unit

Terminates the process. It is equivalent to kill Sys.sigkill on Unix but also works on Windows (unlike Lwt_process.process_none.kill).

method status : Unix.process_status Lwt.t

Threads which wait for the sub-process to exit then returns its exit status

Threads which wait for the sub-process to exit then returns its resource usages

method close : Unix.process_status Lwt.t

Closes the process and returns its exit status. This closes all channels used to communicate with the process

diff --git a/dev/lwt/Lwt_process/class-process_out/index.html b/dev/lwt/Lwt_process/class-process_out/index.html new file mode 100644 index 00000000..6d2b388f --- /dev/null +++ b/dev/lwt/Lwt_process/class-process_out/index.html @@ -0,0 +1,2 @@ + +process_out (lwt.Lwt_process.process_out)

Class Lwt_process.process_out

inherit process_none
method stdin : Lwt_io.output_channel

The standard input of the process

diff --git a/dev/lwt/Lwt_process/index.html b/dev/lwt/Lwt_process/index.html new file mode 100644 index 00000000..72326278 --- /dev/null +++ b/dev/lwt/Lwt_process/index.html @@ -0,0 +1,173 @@ + +Lwt_process (lwt.Lwt_process)

Module Lwt_process

Process management

This module allows you to spawn processes and communicate with them.

type command = string * string array

A command. The first field is the name of the executable and the second is the list of arguments. For example:

("ls", [|"ls"; "-l"|])

Notes:

  • if the name is the empty string, then the first argument will be used. You should specify a name only if you do not want the executable to be searched in the PATH. On Windows the only way to enable automatic search in PATH is to pass an empty name.
  • it is possible to ``inline'' an argument, i.e. split it into multiple arguments. To do that prefix it with "\000". For example:
("", [|"echo"; "\000foo bar"|])

is the same as:

("", [|"echo"; "foo"; "bar"|])
val shell : string -> command

A command executed with the shell. (with "/bin/sh -c <cmd>" on Unix and "cmd.exe /c <cmd>" on Windows).

All the following functions take an optional argument timeout, in seconds. If specified, after expiration, the process will be sent a Unix.sigkill signal and channels will be closed. When the channels are closed, any pending I/O operations on them (such as Lwt_io.read_chars) fail with exception Lwt_io.Channel_closed.

High-level functions

Redirections

type redirection = [
  1. | `Keep
    (*

    Point to the same file as in the parent.

    *)
  2. | `Dev_null
    (*

    Redirect to /dev/null (POSIX) or nul (Win32).

    *)
  3. | `Close
    (*

    Close the file descriptor.

    *)
  4. | `FD_copy of Unix.file_descr
    (*

    Redirect to the file pointed to by fd. fd remains open in the parent.

    *)
  5. | `FD_move of Unix.file_descr
    (*

    Redirect to the file pointed to by fd. fd is then closed in the parent.

    *)
]

File descriptor redirections. These are used with the ~stdin, ~stdout, and ~stderr arguments below to specify how the standard file descriptors should be redirected in the child process. All optional redirection arguments default to `Keep.

Executing

val exec : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdin:redirection -> + ?stdout:redirection -> + ?stderr:redirection -> + command -> + Unix.process_status Lwt.t

Executes the given command and returns its exit status.

Receiving

val pread : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdin:redirection -> + ?stderr:redirection -> + command -> + string Lwt.t
val pread_chars : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdin:redirection -> + ?stderr:redirection -> + command -> + char Lwt_stream.t
val pread_line : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdin:redirection -> + ?stderr:redirection -> + command -> + string Lwt.t
val pread_lines : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdin:redirection -> + ?stderr:redirection -> + command -> + string Lwt_stream.t

Sending

val pwrite : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdout:redirection -> + ?stderr:redirection -> + command -> + string -> + unit Lwt.t
val pwrite_chars : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdout:redirection -> + ?stderr:redirection -> + command -> + char Lwt_stream.t -> + unit Lwt.t
val pwrite_line : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdout:redirection -> + ?stderr:redirection -> + command -> + string -> + unit Lwt.t
val pwrite_lines : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdout:redirection -> + ?stderr:redirection -> + command -> + string Lwt_stream.t -> + unit Lwt.t

Mapping

val pmap : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stderr:redirection -> + command -> + string -> + string Lwt.t
val pmap_chars : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stderr:redirection -> + command -> + char Lwt_stream.t -> + char Lwt_stream.t
val pmap_line : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stderr:redirection -> + command -> + string -> + string Lwt.t
val pmap_lines : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stderr:redirection -> + command -> + string Lwt_stream.t -> + string Lwt_stream.t

Spawning processes

type state =
  1. | Running
    (*

    The process is still running

    *)
  2. | Exited of Unix.process_status
    (*

    The process has exited

    *)

State of a sub-process

class process_none : ?timeout:float -> ?env:string array -> ?cwd:string -> ?stdin:redirection -> ?stdout: + redirection -> ?stderr:redirection -> command -> object ... end
val open_process_none : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdin:redirection -> + ?stdout:redirection -> + ?stderr:redirection -> + command -> + process_none
val with_process_none : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdin:redirection -> + ?stdout:redirection -> + ?stderr:redirection -> + command -> + (process_none -> 'a Lwt.t) -> + 'a Lwt.t
class process_in : ?timeout:float -> ?env:string array -> ?cwd:string -> ?stdin:redirection -> ?stderr: + redirection -> command -> object ... end
val open_process_in : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdin:redirection -> + ?stderr:redirection -> + command -> + process_in
val with_process_in : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdin:redirection -> + ?stderr:redirection -> + command -> + (process_in -> 'a Lwt.t) -> + 'a Lwt.t
class process_out : ?timeout:float -> ?env:string array -> ?cwd:string -> ?stdout:redirection -> ?stderr: + redirection -> command -> object ... end
val open_process_out : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdout:redirection -> + ?stderr:redirection -> + command -> + process_out
val with_process_out : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stdout:redirection -> + ?stderr:redirection -> + command -> + (process_out -> 'a Lwt.t) -> + 'a Lwt.t
class process : ?timeout:float -> ?env:string array -> ?cwd:string -> ?stderr:redirection -> + command -> object ... end
val open_process : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stderr:redirection -> + command -> + process
val with_process : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + ?stderr:redirection -> + command -> + (process -> 'a Lwt.t) -> + 'a Lwt.t
class process_full : ?timeout:float -> ?env:string array -> ?cwd:string -> command -> object ... end
val open_process_full : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + command -> + process_full
val with_process_full : + ?timeout:float -> + ?env:string array -> + ?cwd:string -> + command -> + (process_full -> 'a Lwt.t) -> + 'a Lwt.t
diff --git a/dev/lwt/Lwt_result/Infix/index.html b/dev/lwt/Lwt_result/Infix/index.html new file mode 100644 index 00000000..0c50cdb1 --- /dev/null +++ b/dev/lwt/Lwt_result/Infix/index.html @@ -0,0 +1,2 @@ + +Infix (lwt.Lwt_result.Infix)

Module Lwt_result.Infix

val (>|=) : ('a, 'e) t -> ('a -> 'b) -> ('b, 'e) t
val (>>=) : ('a, 'e) t -> ('a -> ('b, 'e) t) -> ('b, 'e) t
diff --git a/dev/lwt/Lwt_result/Let_syntax/Let_syntax/Open_on_rhs/index.html b/dev/lwt/Lwt_result/Let_syntax/Let_syntax/Open_on_rhs/index.html new file mode 100644 index 00000000..a9745c76 --- /dev/null +++ b/dev/lwt/Lwt_result/Let_syntax/Let_syntax/Open_on_rhs/index.html @@ -0,0 +1,2 @@ + +Open_on_rhs (lwt.Lwt_result.Let_syntax.Let_syntax.Open_on_rhs)

Module Let_syntax.Open_on_rhs

diff --git a/dev/lwt/Lwt_result/Let_syntax/Let_syntax/index.html b/dev/lwt/Lwt_result/Let_syntax/Let_syntax/index.html new file mode 100644 index 00000000..dd06da79 --- /dev/null +++ b/dev/lwt/Lwt_result/Let_syntax/Let_syntax/index.html @@ -0,0 +1,2 @@ + +Let_syntax (lwt.Lwt_result.Let_syntax.Let_syntax)

Module Let_syntax.Let_syntax

val return : 'a -> ('a, _) t
val map : ('a, 'e) t -> f:('a -> 'b) -> ('b, 'e) t
val bind : ('a, 'e) t -> f:('a -> ('b, 'e) t) -> ('b, 'e) t
val both : ('a, 'e) t -> ('b, 'e) t -> ('a * 'b, 'e) t
module Open_on_rhs : sig ... end
diff --git a/dev/lwt/Lwt_result/Let_syntax/index.html b/dev/lwt/Lwt_result/Let_syntax/index.html new file mode 100644 index 00000000..4739ffb7 --- /dev/null +++ b/dev/lwt/Lwt_result/Let_syntax/index.html @@ -0,0 +1,2 @@ + +Let_syntax (lwt.Lwt_result.Let_syntax)

Module Lwt_result.Let_syntax

module Let_syntax : sig ... end
diff --git a/dev/lwt/Lwt_result/Syntax/index.html b/dev/lwt/Lwt_result/Syntax/index.html new file mode 100644 index 00000000..11401b91 --- /dev/null +++ b/dev/lwt/Lwt_result/Syntax/index.html @@ -0,0 +1,2 @@ + +Syntax (lwt.Lwt_result.Syntax)

Module Lwt_result.Syntax

Let syntax

Monadic syntax

val let* : ('a, 'e) t -> ('a -> ('b, 'e) t) -> ('b, 'e) t

Syntax for bind.

val and* : ('a, 'e) t -> ('b, 'e) t -> ('a * 'b, 'e) t

Syntax for both.

Applicative syntax

val let+ : ('a, 'e) t -> ('a -> 'b) -> ('b, 'e) t

Syntax for map.

val and+ : ('a, 'e) t -> ('b, 'e) t -> ('a * 'b, 'e) t

Syntax for both.

diff --git a/dev/lwt/Lwt_result/index.html b/dev/lwt/Lwt_result/index.html new file mode 100644 index 00000000..d8248cde --- /dev/null +++ b/dev/lwt/Lwt_result/index.html @@ -0,0 +1,2 @@ + +Lwt_result (lwt.Lwt_result)

Module Lwt_result

Explicit error handling

This module provides helpers for values of type ('a, 'b) result Lwt.t. The module is experimental and may change in the future.

type (+'a, +'b) t = ('a, 'b) result Lwt.t
val return : 'a -> ('a, _) t
val fail : 'b -> (_, 'b) t
val lift : ('a, 'b) result -> ('a, 'b) t
val ok : 'a Lwt.t -> ('a, _) t
val error : 'b Lwt.t -> (_, 'b) t
  • since 5.6.0
val catch : (unit -> 'a Lwt.t) -> ('a, exn) t

catch x behaves like return y if x () evaluates to y, and like fail e if x () raises e

val get_exn : ('a, exn) t -> 'a Lwt.t

get_exn is the opposite of catch: it unwraps the result type, returning the value in case of success, calls Lwt.fail in case of error.

val map : ('a -> 'b) -> ('a, 'e) t -> ('b, 'e) t
val map_error : ('e1 -> 'e2) -> ('a, 'e1) t -> ('a, 'e2) t
  • since 5.6.0
val bind : ('a, 'e) t -> ('a -> ('b, 'e) t) -> ('b, 'e) t
val bind_error : ('a, 'e1) t -> ('e1 -> ('a, 'e2) t) -> ('a, 'e2) t
  • since 5.6.0
val bind_lwt : ('a, 'e) t -> ('a -> 'b Lwt.t) -> ('b, 'e) t
val bind_lwt_error : ('a, 'e1) t -> ('e1 -> 'e2 Lwt.t) -> ('a, 'e2) t
  • since 5.6.0
val bind_result : ('a, 'e) t -> ('a -> ('b, 'e) result) -> ('b, 'e) t
val both : ('a, 'e) t -> ('b, 'e) t -> ('a * 'b, 'e) t

Lwt.both p_1 p_2 returns a promise that is pending until both promises p_1 and p_2 become resolved. If only p_1 is Error e, the promise is resolved with Error e, If only p_2 is Error e, the promise is resolved with Error e, If both p_1 and p_2 resolve with Error _, the promise is resolved with the error that occurred first.

val iter : ('a -> unit Lwt.t) -> ('a, 'e) t -> unit Lwt.t

iter f r is f v if r is a promise resolved with Ok v, and Lwt.return_unit otherwise.

  • since Lwt 5.6.0
val iter_error : ('e -> unit Lwt.t) -> ('a, 'e) t -> unit Lwt.t

iter_error f r is f v if r is a promise resolved with Error v, and Lwt.return_unit otherwise.

  • since Lwt 5.6.0
module Infix : sig ... end
module Let_syntax : sig ... end
module Syntax : sig ... end
include module type of Infix
val (>|=) : ('a, 'e) t -> ('a -> 'b) -> ('b, 'e) t
val (>>=) : ('a, 'e) t -> ('a -> ('b, 'e) t) -> ('b, 'e) t

Deprecated

val map_err : ('e1 -> 'e2) -> ('a, 'e1) t -> ('a, 'e2) t
  • deprecated

    Alias to map_error since 5.6.0.

val bind_lwt_err : ('a, 'e1) t -> ('e1 -> 'e2 Lwt.t) -> ('a, 'e2) t
  • deprecated

    Alias to bind_lwt_error since 5.6.0.

diff --git a/dev/lwt/Lwt_seq/index.html b/dev/lwt/Lwt_seq/index.html new file mode 100644 index 00000000..65cb68f1 --- /dev/null +++ b/dev/lwt/Lwt_seq/index.html @@ -0,0 +1,2 @@ + +Lwt_seq (lwt.Lwt_seq)

Module Lwt_seq

type 'a t = unit -> 'a node Lwt.t

The type of delayed lists containing elements of type 'a. Note that the concrete list node 'a node is delayed under a closure, not a lazy block, which means it might be recomputed every time we access it.

and +'a node =
  1. | Nil
  2. | Cons of 'a * 'a t
    (*

    A fully-evaluated list node, either empty or containing an element and a delayed tail.

    *)
val empty : 'a t

The empty sequence, containing no elements.

val return : 'a -> 'a t

The singleton sequence containing only the given element.

val return_lwt : 'a Lwt.t -> 'a t

The singleton sequence containing only the given promised element.

val cons : 'a -> 'a t -> 'a t

cons x xs is the sequence containing the element x followed by the sequence xs

val cons_lwt : 'a Lwt.t -> 'a t -> 'a t

cons x xs is the sequence containing the element promised by x followed by the sequence xs

val append : 'a t -> 'a t -> 'a t

append xs ys is the sequence xs followed by the sequence ys

val map : ('a -> 'b) -> 'a t -> 'b t

map f seq returns a new sequence whose elements are the elements of seq, transformed by f. This transformation is lazy, it only applies when the result is traversed.

val map_s : ('a -> 'b Lwt.t) -> 'a t -> 'b t

map_s f seq is like map f seq but f is a function that returns a promise.

Note that there is no concurrency between the promises from the underlying sequence seq and the promises from applying the function f. In other words, the next promise-element of the underlying sequence (seq) is only created when the current promise-element of the returned sequence (as mapped by f) has resolved. This scheduling is true for all the _s functions of this module.

val filter : ('a -> bool) -> 'a t -> 'a t

Remove from the sequence the elements that do not satisfy the given predicate. This transformation is lazy, it only applies when the result is traversed.

val filter_s : ('a -> bool Lwt.t) -> 'a t -> 'a t

filter_s is like filter but the predicate returns a promise.

See map_s for additional details about scheduling.

val filter_map : ('a -> 'b option) -> 'a t -> 'b t

Apply the function to every element; if f x = None then x is dropped; if f x = Some y then y is returned. This transformation is lazy, it only applies when the result is traversed.

val filter_map_s : ('a -> 'b option Lwt.t) -> 'a t -> 'b t

filter_map_s is like filter but the predicate returns a promise.

See map_s for additional details about scheduling.

val flat_map : ('a -> 'b t) -> 'a t -> 'b t

Map each element to a subsequence, then return each element of this sub-sequence in turn. This transformation is lazy, it only applies when the result is traversed.

val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a Lwt.t

Traverse the sequence from left to right, combining each element with the accumulator using the given function. The traversal happens immediately and will not terminate (i.e., the promise will not resolve) on infinite sequences.

val fold_left_s : ('a -> 'b -> 'a Lwt.t) -> 'a -> 'b t -> 'a Lwt.t

fold_left_s is like fold_left but the function returns a promise.

See map_s for additional details about scheduling.

val iter : ('a -> unit) -> 'a t -> unit Lwt.t

Iterate on the sequence, calling the (imperative) function on every element.

The sequence's next node is evaluated only once the function has finished processing the current element. More formally: the promise for the n+1th node of the sequence is created only once the promise returned by f on the nth element of the sequence has resolved.

The traversal happens immediately and will not terminate (i.e., the promise will not resolve) on infinite sequences.

val iter_s : ('a -> unit Lwt.t) -> 'a t -> unit Lwt.t

iter_s is like iter but the function returns a promise.

See map_s for additional details about scheduling.

val iter_p : ('a -> unit Lwt.t) -> 'a t -> unit Lwt.t

Iterate on the sequence, calling the (imperative) function on every element.

The sequence's next node is evaluated as soon as the previous node is resolved.

The traversal happens immediately and will not terminate (i.e., the promise will not resolve) on infinite sequences.

val iter_n : ?max_concurrency:int -> ('a -> unit Lwt.t) -> 'a t -> unit Lwt.t

iter_n ~max_concurrency f s

Iterates on the sequence s, calling the (imperative) function f on every element.

The sum total of unresolved promises returned by f never exceeds max_concurrency. Node suspensions are evaluated only when there is capacity for f-promises to be evaluated. Consequently, there might be significantly fewer than max_concurrency promises being evaluated concurrently; especially if the node suspensions take longer to evaluate than the f-promises.

The traversal happens immediately and will not terminate (i.e., the promise will not resolve) on infinite sequences.

  • parameter max_concurrency

    defaults to 1.

  • raises Invalid_argument

    if max_concurrency < 1.

val unfold : ('b -> ('a * 'b) option) -> 'b -> 'a t

Build a sequence from a step function and an initial value. unfold f u returns empty if the promise f u resolves to None, or fun () -> Lwt.return (Cons (x, unfold f y)) if the promise f u resolves to Some (x, y).

val unfold_lwt : ('b -> ('a * 'b) option Lwt.t) -> 'b -> 'a t

unfold_lwt is like unfold but the step function returns a promise.

val to_list : 'a t -> 'a list Lwt.t

Convert a sequence to a list, preserving order. The traversal happens immediately and will not terminate (i.e., the promise will not resolve) on infinite sequences.

val of_list : 'a list -> 'a t

Convert a list to a sequence, preserving order.

val of_seq : 'a Stdlib.Seq.t -> 'a t

Convert from 'a Stdlib.Seq.t to 'a Lwt_seq.t. This transformation is lazy, it only applies when the result is traversed.

val of_seq_lwt : 'a Lwt.t Stdlib.Seq.t -> 'a t

Convert from 'a Lwt.t Stdlib.Seq.t to 'a Lwt_seq.t. This transformation is lazy, it only applies when the result is traversed.

diff --git a/dev/lwt/Lwt_sequence/index.html b/dev/lwt/Lwt_sequence/index.html new file mode 100644 index 00000000..81b812f7 --- /dev/null +++ b/dev/lwt/Lwt_sequence/index.html @@ -0,0 +1,2 @@ + +Lwt_sequence (lwt.Lwt_sequence)

Module Lwt_sequence

Mutable sequence of elements (deprecated)

A sequence is an object holding a list of elements which support the following operations:

type 'a t

Type of a sequence holding values of type 'a

type 'a node

Type of a node holding one value of type 'a in a sequence

Operation on nodes

val get : 'a node -> 'a

Returns the contents of a node

val set : 'a node -> 'a -> unit

Change the contents of a node

val remove : 'a node -> unit

Removes a node from the sequence it is part of. It does nothing if the node has already been removed.

Operations on sequence

val create : unit -> 'a t

create () creates a new empty sequence

val clear : 'a t -> unit

Removes all nodes from the given sequence. The nodes are not actually mutated to note their removal. Only the sequence's pointers are updated.

val is_empty : 'a t -> bool

Returns true iff the given sequence is empty

val length : 'a t -> int

Returns the number of elements in the given sequence. This is a O(n) operation where n is the number of elements in the sequence.

val add_l : 'a -> 'a t -> 'a node

add_l x s adds x to the left of the sequence s

val add_r : 'a -> 'a t -> 'a node

add_r x s adds x to the right of the sequence s

exception Empty

Exception raised by take_l and take_r and when the sequence is empty

val take_l : 'a t -> 'a

take_l x s remove and returns the leftmost element of s

  • raises Empty

    if the sequence is empty

val take_r : 'a t -> 'a

take_r x s remove and returns the rightmost element of s

  • raises Empty

    if the sequence is empty

val take_opt_l : 'a t -> 'a option

take_opt_l x s remove and returns Some x where x is the leftmost element of s or None if s is empty

val take_opt_r : 'a t -> 'a option

take_opt_r x s remove and returns Some x where x is the rightmost element of s or None if s is empty

val transfer_l : 'a t -> 'a t -> unit

transfer_l s1 s2 removes all elements of s1 and add them at the left of s2. This operation runs in constant time and space.

val transfer_r : 'a t -> 'a t -> unit

transfer_r s1 s2 removes all elements of s1 and add them at the right of s2. This operation runs in constant time and space.

Sequence iterators

Note: it is OK to remove a node while traversing a sequence

val iter_l : ('a -> unit) -> 'a t -> unit

iter_l f s applies f on all elements of s starting from the left

val iter_r : ('a -> unit) -> 'a t -> unit

iter_r f s applies f on all elements of s starting from the right

val iter_node_l : ('a node -> unit) -> 'a t -> unit

iter_node_l f s applies f on all nodes of s starting from the left

val iter_node_r : ('a node -> unit) -> 'a t -> unit

iter_node_r f s applies f on all nodes of s starting from the right

val fold_l : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b

fold_l f s is:

fold_l f s x = f en (... (f e2 (f e1 x)))

where e1, e2, ..., en are the elements of s

val fold_r : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b

fold_r f s is:

fold_r f s x = f e1 (f e2 (... (f en x)))

where e1, e2, ..., en are the elements of s

val find_node_opt_l : ('a -> bool) -> 'a t -> 'a node option

find_node_opt_l f s returns Some x, where x is the first node of s starting from the left that satisfies f or None if none exists.

val find_node_opt_r : ('a -> bool) -> 'a t -> 'a node option

find_node_opt_r f s returns Some x, where x is the first node of s starting from the right that satisfies f or None if none exists.

val find_node_l : ('a -> bool) -> 'a t -> 'a node

find_node_l f s returns the first node of s starting from the left that satisfies f or raises Not_found if none exists.

val find_node_r : ('a -> bool) -> 'a t -> 'a node

find_node_r f s returns the first node of s starting from the right that satisfies f or raises Not_found if none exists.

diff --git a/dev/lwt/Lwt_stream/class-type-bounded_push/index.html b/dev/lwt/Lwt_stream/class-type-bounded_push/index.html new file mode 100644 index 00000000..add9ce61 --- /dev/null +++ b/dev/lwt/Lwt_stream/class-type-bounded_push/index.html @@ -0,0 +1,2 @@ + +bounded_push (lwt.Lwt_stream.bounded_push)

Class type Lwt_stream.bounded_push

Type of sources for bounded push-streams.

method size : int

Size of the stream.

method resize : int -> unit

Change the size of the stream queue. Note that the new size can smaller than the current stream queue size.

It raises Stdlib.Invalid_argument if size < 0.

method push : 'a -> unit Lwt.t

Pushes a new element to the stream. If the stream is full then it will block until one element is consumed. If another thread is already blocked on push, it raises Lwt_stream.Full.

method close : unit

Closes the stream. Any thread currently blocked on Lwt_stream.bounded_push.push fails with Lwt_stream.Closed.

method count : int

Number of elements in the stream queue.

method blocked : bool

Is a thread is blocked on Lwt_stream.bounded_push.push ?

method closed : bool

Is the stream closed ?

method set_reference : 'a. 'a -> unit

Set the reference to an external source.

diff --git a/dev/lwt/Lwt_stream/index.html b/dev/lwt/Lwt_stream/index.html new file mode 100644 index 00000000..de6f0cdd --- /dev/null +++ b/dev/lwt/Lwt_stream/index.html @@ -0,0 +1,21 @@ + +Lwt_stream (lwt.Lwt_stream)

Module Lwt_stream

Data streams

type 'a t

A stream holding values of type 'a.

Naming convention: in this module, all functions applying a function to each element of a stream are suffixed by:

  • _s when the function returns a thread and calls are serialised
  • _p when the function returns a thread and calls are parallelised

Construction

val from : (unit -> 'a option Lwt.t) -> 'a t

from f creates a stream from the given input function. f is called each time more input is needed, and the stream ends when f returns None.

If f, or the thread produced by f, raises an exception, that exception is forwarded to the consumer of the stream (for example, a caller of get). Note that this does not end the stream. A subsequent attempt to read from the stream will cause another call to f, which may succeed with a value.

val from_direct : (unit -> 'a option) -> 'a t

from_direct f does the same as from but with a function that does not return a thread. It is preferred that this function be used rather than wrapping f into a function which returns a thread.

The behavior when f raises an exception is the same as for from, except that f does not produce a thread.

exception Closed

Exception raised by the push function of a push-stream when pushing an element after the end of stream (= None) has been pushed.

val create : unit -> 'a t * ('a option -> unit)

create () returns a new stream and a push function.

To notify the stream's consumer of errors, either use a separate communication channel, or use a Stdlib.result stream. There is no way to push an exception into a push-stream.

val create_with_reference : unit -> 'a t * ('a option -> unit) * ('b -> unit)

create_with_reference () returns a new stream and a push function. The last function allows a reference to be set to an external source. This prevents the external source from being garbage collected.

For example, to convert a reactive event to a stream:

let stream, push, set_ref = Lwt_stream.create_with_reference () in
+set_ref (map_event push event)
exception Full

Exception raised by the push function of a bounded push-stream when the stream queue is full and a thread is already waiting to push an element.

class type 'a bounded_push = object ... end

Type of sources for bounded push-streams.

val create_bounded : int -> 'a t * 'a bounded_push

create_bounded size returns a new stream and a bounded push source. The stream can hold a maximum of size elements. When this limit is reached, pushing a new element will block until one is consumed.

Note that you cannot clone or parse (with parse) a bounded stream. These functions will raise Invalid_argument if you try to do so.

It raises Invalid_argument if size < 0.

val return : 'a -> 'a t

return a creates a stream containing the value a and being immediately closed stream (in the sense of is_closed).

  • since 5.5.0
val return_lwt : 'a Lwt.t -> 'a t

return_lwt l creates a stream returning the value that l resolves to. The value is pushed into the stream immediately after the promise becomes resolved and the stream is then immediately closed (in the sense of is_closed).

If, instead, l becomes rejected, then the stream is closed without any elements in it. Attempting to fetch elements from it will raise Empty.

  • since 5.5.0
val of_seq : 'a Stdlib.Seq.t -> 'a t

of_seq s creates a stream returning all elements of s. The elements are evaluated from s and pushed onto the stream as the stream is consumed.

  • since 4.2.0
val of_lwt_seq : 'a Lwt_seq.t -> 'a t

of_lwt_seq s creates a stream returning all elements of s. The elements are evaluated from s and pushed onto the stream as the stream is consumed.

  • since 5.5.0
val of_list : 'a list -> 'a t

of_list l creates a stream returning all elements of l. The elements are pushed into the stream immediately, resulting in a closed stream (in the sense of is_closed).

val of_array : 'a array -> 'a t

of_array a creates a stream returning all elements of a. The elements are pushed into the stream immediately, resulting in a closed stream (in the sense of is_closed).

val of_string : string -> char t

of_string str creates a stream returning all characters of str. The characters are pushed into the stream immediately, resulting in a closed stream (in the sense of is_closed).

val clone : 'a t -> 'a t

clone st clone the given stream. Operations on each stream will not affect the other.

For example:

# let st1 = Lwt_stream.of_list [1; 2; 3];;
+val st1 : int Lwt_stream.t = <abstr>
+# let st2 = Lwt_stream.clone st1;;
+val st2 : int Lwt_stream.t = <abstr>
+# lwt x = Lwt_stream.next st1;;
+val x : int = 1
+# lwt y = Lwt_stream.next st2;;
+val y : int = 1

It raises Invalid_argument if st is a bounded push-stream.

Destruction

val to_list : 'a t -> 'a list Lwt.t

Returns the list of elements of the given stream

val to_string : char t -> string Lwt.t

Returns the word composed of all characters of the given stream

Data retrieval

exception Empty

Exception raised when trying to retrieve data from an empty stream.

val peek : 'a t -> 'a option Lwt.t

peek st returns the first element of the stream, if any, without removing it.

val npeek : int -> 'a t -> 'a list Lwt.t

npeek n st returns at most the first n elements of st, without removing them.

val get : 'a t -> 'a option Lwt.t

get st removes and returns the first element of the stream, if any.

val nget : int -> 'a t -> 'a list Lwt.t

nget n st removes and returns at most the first n elements of st.

val get_while : ('a -> bool) -> 'a t -> 'a list Lwt.t
val get_while_s : ('a -> bool Lwt.t) -> 'a t -> 'a list Lwt.t

get_while f st returns the longest prefix of st where all elements satisfy f.

val next : 'a t -> 'a Lwt.t

next st removes and returns the next element of the stream or fails with Empty, if the stream is empty.

val last_new : 'a t -> 'a Lwt.t

last_new st returns the last element that can be obtained without sleeping, or wait for one if none is available.

It fails with Empty if the stream has no more elements.

val junk : 'a t -> unit Lwt.t

junk st removes the first element of st.

val njunk : int -> 'a t -> unit Lwt.t

njunk n st removes at most the first n elements of the stream.

val junk_while : ('a -> bool) -> 'a t -> unit Lwt.t
val junk_while_s : ('a -> bool Lwt.t) -> 'a t -> unit Lwt.t

junk_while f st removes all elements at the beginning of the streams which satisfy f.

val junk_old : 'a t -> unit Lwt.t

junk_old st removes all elements that are ready to be read without yielding from st.

val get_available : 'a t -> 'a list

get_available st returns all available elements of l without blocking.

val get_available_up_to : int -> 'a t -> 'a list

get_available_up_to n st returns up to n elements of l without blocking.

val is_empty : 'a t -> bool Lwt.t

is_empty st returns whether the given stream is empty.

val is_closed : 'a t -> bool

is_closed st returns whether the given stream has been closed. A closed stream is not necessarily empty. It may still contain unread elements. If is_closed s = true, then all subsequent reads until the end of the stream are guaranteed not to block.

  • since 2.6.0
val closed : 'a t -> unit Lwt.t

closed st returns a thread that will sleep until the stream has been closed.

  • since 2.6.0

Stream transversal

Note: all the following functions are destructive.

For example:

# let st1 = Lwt_stream.of_list [1; 2; 3];;
+val st1 : int Lwt_stream.t = <abstr>
+# let st2 = Lwt_stream.map string_of_int st1;;
+val st2 : string Lwt_stream.t = <abstr>
+# lwt x = Lwt_stream.next st1;;
+val x : int = 1
+# lwt y = Lwt_stream.next st2;;
+val y : string = "2"
val choose : 'a t list -> 'a t

choose l creates an stream from a list of streams. The resulting stream will return elements returned by any stream of l in an unspecified order.

val map : ('a -> 'b) -> 'a t -> 'b t
val map_s : ('a -> 'b Lwt.t) -> 'a t -> 'b t

map f st maps the value returned by st with f

val filter : ('a -> bool) -> 'a t -> 'a t
val filter_s : ('a -> bool Lwt.t) -> 'a t -> 'a t

filter f st keeps only values, x, such that f x is true

val filter_map : ('a -> 'b option) -> 'a t -> 'b t
val filter_map_s : ('a -> 'b option Lwt.t) -> 'a t -> 'b t

filter_map f st filter and map st at the same time

val map_list : ('a -> 'b list) -> 'a t -> 'b t
val map_list_s : ('a -> 'b list Lwt.t) -> 'a t -> 'b t

map_list f st applies f on each element of st and flattens the lists returned

val fold : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b Lwt.t
val fold_s : ('a -> 'b -> 'b Lwt.t) -> 'a t -> 'b -> 'b Lwt.t

fold f s x fold_like function for streams.

val iter : ('a -> unit) -> 'a t -> unit Lwt.t
val iter_p : ('a -> unit Lwt.t) -> 'a t -> unit Lwt.t
val iter_s : ('a -> unit Lwt.t) -> 'a t -> unit Lwt.t

iter f s iterates over all elements of the stream.

val iter_n : ?max_concurrency:int -> ('a -> unit Lwt.t) -> 'a t -> unit Lwt.t

iter_n ?max_concurrency f s iterates over all elements of the stream s. Iteration is performed concurrently with up to max_threads concurrent instances of f.

Iteration is not guaranteed to be in order as this function will attempt to always process max_concurrency elements from s at once.

  • parameter max_concurrency

    defaults to 1.

  • raises Invalid_argument

    if max_concurrency < 1.

  • since 3.3.0
val find : ('a -> bool) -> 'a t -> 'a option Lwt.t
val find_s : ('a -> bool Lwt.t) -> 'a t -> 'a option Lwt.t

find f s find an element in a stream.

val find_map : ('a -> 'b option) -> 'a t -> 'b option Lwt.t
val find_map_s : ('a -> 'b option Lwt.t) -> 'a t -> 'b option Lwt.t

find_map f s find and map at the same time.

val combine : 'a t -> 'b t -> ('a * 'b) t

combine s1 s2 combines two streams. The stream will end when either stream ends.

val append : 'a t -> 'a t -> 'a t

append s1 s2 returns a stream which returns all elements of s1, then all elements of s2

val concat : 'a t t -> 'a t

concat st returns the concatenation of all streams of st.

val flatten : 'a list t -> 'a t

flatten st = map_list (fun l -> l) st

val wrap_exn : 'a t -> ('a, exn) result t

wrap_exn s is a stream s' such that each time s yields a value v, s' yields Result.Ok v, and when the source of s raises an exception e, s' yields Result.Error e.

Note that push-streams (as returned by create) never raise exceptions.

If the stream source keeps raising the same exception e each time the stream is read, s' is unbounded. Reading it will produce Result.Error e indefinitely.

  • since 2.7.0

Parsing

val parse : 'a t -> ('a t -> 'b Lwt.t) -> 'b Lwt.t

parse st f parses st with f. If f raise an exception, st is restored to its previous state.

It raises Invalid_argument if st is a bounded push-stream.

Misc

val hexdump : char t -> string t

hexdump byte_stream returns a stream which is the same as the output of hexdump -C.

Basically, here is a simple implementation of hexdump -C:

let () = Lwt_main.run begin
+    Lwt_io.write_lines
+      Lwt_io.stdout
+      (Lwt_stream.hexdump (Lwt_io.read_lines Lwt_io.stdin))
+  end
diff --git a/dev/lwt/Lwt_switch/index.html b/dev/lwt/Lwt_switch/index.html new file mode 100644 index 00000000..642cb112 --- /dev/null +++ b/dev/lwt/Lwt_switch/index.html @@ -0,0 +1,16 @@ + +Lwt_switch (lwt.Lwt_switch)

Module Lwt_switch

Lwt switches

Switch has two goals:

For example, consider the following interface:

type id
+
+val free : id -> unit Lwt.t
+
+val f : unit -> id Lwt.t
+val g : unit -> id Lwt.t
+val h : unit -> id Lwt.t

Now you want to call f, g and h in parallel. You can simply do:

lwt idf = f () and idg = g () and idh = h () in
+...

However, one may want to handle possible failures of f (), g () and h (), and disable all allocated resources if one of these three threads fails. This may be hard since you have to remember which one failed and which one returned correctly.

Now if we change the interface a little bit:

val f : ?switch : Lwt_switch.t -> unit -> id Lwt.t
+val g : ?switch : Lwt_switch.t -> unit -> id Lwt.t
+val h : ?switch : Lwt_switch.t -> unit -> id Lwt.t

the code becomes:

Lwt_switch.with_switch (fun switch ->
+  lwt idf = f ~switch ()
+  and idg = g ~switch ()
+  and idh = h ~switch () in
+  ...
+)
type t

Type of switches.

val create : unit -> t

create () creates a new switch.

val with_switch : (t -> 'a Lwt.t) -> 'a Lwt.t

with_switch fn is fn switch, where switch is a fresh switch that is turned off when the callback thread finishes (whether it succeeds or fails).

  • since 2.6.0
val is_on : t -> bool

is_on switch returns true if the switch is currently on, and false otherwise.

val turn_off : t -> unit Lwt.t

turn_off switch turns off the switch. It calls all registered hooks, waits for all of them to terminate, then returns. If one of the hooks failed, it will fail with the exception raised by the hook. If the switch is already off, it does nothing.

exception Off

Exception raised when trying to add a hook to a switch that is already off.

val check : t option -> unit

check switch does nothing if switch is None or contains an switch that is currently on, and raises Off otherwise.

val add_hook : t option -> (unit -> unit Lwt.t) -> unit

add_hook switch f registers f so it will be called when turn_off is invoked. It does nothing if switch is None. If switch contains an switch that is already off then Off is raised.

val add_hook_or_exec : t option -> (unit -> unit Lwt.t) -> unit Lwt.t

add_hook_or_exec switch f is the same as add_hook except that if the switch is already off, f is called immediately.

diff --git a/dev/lwt/Lwt_sys/index.html b/dev/lwt/Lwt_sys/index.html new file mode 100644 index 00000000..3477a68e --- /dev/null +++ b/dev/lwt/Lwt_sys/index.html @@ -0,0 +1,2 @@ + +Lwt_sys (lwt.Lwt_sys)

Module Lwt_sys

System informations.

exception Not_available of string

Not_available(feature) is an exception that may be raised when a feature is not available on the current system.

type feature = [
  1. | `wait4
  2. | `get_cpu
  3. | `get_affinity
  4. | `set_affinity
  5. | `recv_msg
  6. | `send_msg
  7. | `fd_passing
  8. | `get_credentials
  9. | `mincore
  10. | `madvise
  11. | `fdatasync
  12. | `libev
]

Features that can be tested.

val have : feature -> bool

Test whether the given feature is available on the current system.

type byte_order =
  1. | Little_endian
  2. | Big_endian
    (*

    Type of byte order

    *)
val byte_order : byte_order

The byte order used by the computer running the program.

val windows : bool
  • deprecated

    Use Sys.win32.

diff --git a/dev/lwt/Lwt_throttle/Make/argument-1-H/index.html b/dev/lwt/Lwt_throttle/Make/argument-1-H/index.html new file mode 100644 index 00000000..c987c769 --- /dev/null +++ b/dev/lwt/Lwt_throttle/Make/argument-1-H/index.html @@ -0,0 +1,2 @@ + +H (lwt.Lwt_throttle.Make.H)

Parameter Make.H

type t

The type of the hashtable keys.

val equal : t -> t -> bool

The equality predicate used to compare keys.

val hash : t -> int

A hashing function on keys. It must be such that if two keys are equal according to equal, then they have identical hash values as computed by hash. Examples: suitable (equal, hash) pairs for arbitrary key types include

  • ((=), hash) for comparing objects by structure (provided objects do not contain floats)
  • ((fun x y -> compare x y = 0), hash) for comparing objects by structure and handling Stdlib.nan correctly
  • ((==), hash) for comparing objects by physical equality (e.g. for mutable or cyclic objects).
diff --git a/dev/lwt/Lwt_throttle/Make/index.html b/dev/lwt/Lwt_throttle/Make/index.html new file mode 100644 index 00000000..55ebebbe --- /dev/null +++ b/dev/lwt/Lwt_throttle/Make/index.html @@ -0,0 +1,2 @@ + +Make (lwt.Lwt_throttle.Make)

Module Lwt_throttle.Make

Parameters

Signature

type key = H.t
type t
val create : rate:int -> max:int -> n:int -> t

Creates a rate limiter.

  • parameter rate

    Maximum number of promise resolutions per second, per channel.

  • parameter max

    Maximum number of pending promises allowed at once, over all channels.

  • parameter n

    Initial size of the internal channel hash table. This should be approximately the number of different channels that will be used.

val wait : t -> key -> bool Lwt.t

Lwt_throttle.wait limiter channel returns a new promise associated with the given rate limiter and channel.

If the maximum number of pending promises for limiter has not been reached, the promise starts pending. It will be resolved with true at some future time, such that the rate limit of limiter is not exceeded, with respect to other promises in the same channel.

If the maximum number of pending promises has been reached, the returned promise is already resolved with false.

diff --git a/dev/lwt/Lwt_throttle/index.html b/dev/lwt/Lwt_throttle/index.html new file mode 100644 index 00000000..69442973 --- /dev/null +++ b/dev/lwt/Lwt_throttle/index.html @@ -0,0 +1,2 @@ + +Lwt_throttle (lwt.Lwt_throttle)

Module Lwt_throttle

Rate limiters.

A rate limiter allows generating sets of promises that will be resolved in the future, at a maximum rate of N promises per second.

The rate limiters in this module support multiple channels, each given a different key by the user. The rate limit applies to each channel independently.

module type S = sig ... end
module Make (H : Stdlib.Hashtbl.HashedType) : S with type key = H.t
diff --git a/dev/lwt/Lwt_throttle/module-type-S/index.html b/dev/lwt/Lwt_throttle/module-type-S/index.html new file mode 100644 index 00000000..937025d9 --- /dev/null +++ b/dev/lwt/Lwt_throttle/module-type-S/index.html @@ -0,0 +1,2 @@ + +S (lwt.Lwt_throttle.S)

Module type Lwt_throttle.S

type key
type t
val create : rate:int -> max:int -> n:int -> t

Creates a rate limiter.

  • parameter rate

    Maximum number of promise resolutions per second, per channel.

  • parameter max

    Maximum number of pending promises allowed at once, over all channels.

  • parameter n

    Initial size of the internal channel hash table. This should be approximately the number of different channels that will be used.

val wait : t -> key -> bool Lwt.t

Lwt_throttle.wait limiter channel returns a new promise associated with the given rate limiter and channel.

If the maximum number of pending promises for limiter has not been reached, the promise starts pending. It will be resolved with true at some future time, such that the rate limit of limiter is not exceeded, with respect to other promises in the same channel.

If the maximum number of pending promises has been reached, the returned promise is already resolved with false.

diff --git a/dev/lwt/Lwt_timeout/index.html b/dev/lwt/Lwt_timeout/index.html new file mode 100644 index 00000000..fb7e2128 --- /dev/null +++ b/dev/lwt/Lwt_timeout/index.html @@ -0,0 +1,2 @@ + +Lwt_timeout (lwt.Lwt_timeout)

Module Lwt_timeout

Cancelable timeouts.

type t
val create : int -> (unit -> unit) -> t

Lwt_timeout.create n f creates a new timeout object with duration n seconds. f is the action, a function to be called once the timeout expires. f should not raise exceptions.

The timeout is not started until Lwt_timeout.start is called on it.

val start : t -> unit

Starts the given timeout.

Starting a timeout that has already been started has the same effect as stopping it, and then restarting it with its original duration. So, suppose you have timeout with a duration of three seconds, which was started two seconds ago. The next call to its action is scheduled for one second in the future. Calling Lwt_timeout.start timeout at this point cancels this upcoming action call, and schedules a call three seconds from now.

val stop : t -> unit

Stops (cancels) the given timeout.

val change : t -> int -> unit

Changes the duration of the given timeout.

If the timeout has already been started, it is stopped, and restarted with its new duration. This is similar to how Lwt_timeout.start works on a timeout that has already been started.

val set_exn_handler : (exn -> unit) -> unit

Lwt_timeout.set_exn_handler f sets the handler to be used for exceptions raised by timeout actions. Recall that actions are not allowed to raise exceptions. If they do raise an exception exn despite this, f exn is called.

The default behavior of f exn, set by Lwt_timeout on program startup, is to pass exn to !Lwt.async_exception_hook. The default behavior of that is to terminate the process.

diff --git a/dev/lwt/Lwt_unix/IO_vectors/index.html b/dev/lwt/Lwt_unix/IO_vectors/index.html new file mode 100644 index 00000000..fd583529 --- /dev/null +++ b/dev/lwt/Lwt_unix/IO_vectors/index.html @@ -0,0 +1,4 @@ + +IO_vectors (lwt.Lwt_unix.IO_vectors)

Module Lwt_unix.IO_vectors

Sequences of buffer slices for writev.

type t

Mutable sequences of I/O vectors. An I/O vector describes a slice of a bytes or Bigarray buffer. Each I/O vector is a triple containing a reference to the buffer, an offset into the buffer where the slice begins, and the length of the slice.

Type abbreviation equivalent to Lwt_bytes.t. Do not use this type name directly; use Lwt_bytes.t instead.

val create : unit -> t

Creates an empty I/O vector sequence.

val append_bytes : t -> bytes -> int -> int -> unit

append_bytes vs buffer offset length appends a slice of the bytes buffer buffer beginning at offset and with length length to the I/O vector sequence vs.

val append_bigarray : t -> _bigarray -> int -> int -> unit

append_bigarray vs buffer offset length appends a slice of the Bigarray buffer buffer beginning at offset and with length length to the I/O vector sequence vs.

val drop : t -> int -> unit

drop vs n adjusts the I/O vector sequence vs so that it no longer includes its first n bytes.

val is_empty : t -> bool

is_empty vs is true if and only if vs has no I/O vectors, or all I/O vectors in vs have zero bytes.

val byte_count : t -> int

byte_count vs is the total number of bytes in vs.

  • since 4.2.0
val system_limit : int option

Some systems limit the number of I/O vectors that can be passed in a single call to their writev or readv system calls. On those systems, if the limit is n, this value is equal to Some n. On systems without such a limit, the value is equal to None.

Unless you need atomic I/O operations, you can ignore this limit. The Lwt binding automatically respects it internally. See Lwt_unix.writev.

A typical limit is 1024 vectors.

diff --git a/dev/lwt/Lwt_unix/LargeFile/index.html b/dev/lwt/Lwt_unix/LargeFile/index.html new file mode 100644 index 00000000..3142fd33 --- /dev/null +++ b/dev/lwt/Lwt_unix/LargeFile/index.html @@ -0,0 +1,2 @@ + +LargeFile (lwt.Lwt_unix.LargeFile)

Module Lwt_unix.LargeFile

val lseek : file_descr -> int64 -> seek_command -> int64 Lwt.t
val truncate : string -> int64 -> unit Lwt.t
val ftruncate : file_descr -> int64 -> unit Lwt.t
type stats = Unix.LargeFile.stats = {
  1. st_dev : int;
  2. st_ino : int;
  3. st_kind : file_kind;
  4. st_perm : file_perm;
  5. st_uid : int;
  6. st_gid : int;
  7. st_rdev : int;
  8. st_size : int64;
  9. st_atime : float;
  10. st_mtime : float;
  11. st_ctime : float;
}
val stat : string -> stats Lwt.t
val lstat : string -> stats Lwt.t
val fstat : file_descr -> stats Lwt.t
val file_exists : string -> bool Lwt.t

file_exists name tests if a file named name exists.

Note that file_exists behaves similarly to Sys.file_exists:

  • β€œfile” is interpreted as β€œdirectory entry” in this context
  • file_exists name will return false in circumstances that would make stat raise a Unix.Unix_error exception.
diff --git a/dev/lwt/Lwt_unix/Versioned/index.html b/dev/lwt/Lwt_unix/Versioned/index.html new file mode 100644 index 00000000..7bd88308 --- /dev/null +++ b/dev/lwt/Lwt_unix/Versioned/index.html @@ -0,0 +1,9 @@ + +Versioned (lwt.Lwt_unix.Versioned)

Module Lwt_unix.Versioned

Versioned variants of APIs undergoing breaking changes.

val bind_1 : file_descr -> sockaddr -> unit

Old version of Lwt_unix.bind. The current Lwt_unix.bind evaluates to a promise, because the internal bind(2) system call can block if the given socket is a Unix domain socket.

  • since 2.7.0
val bind_2 : file_descr -> sockaddr -> unit Lwt.t

Since Lwt 3.0.0, this is just an alias for Lwt_unix.bind.

  • since 2.7.0
val recv_msg_2 : + socket:file_descr -> + io_vectors:IO_vectors.t -> + (int * Unix.file_descr list) Lwt.t

Since Lwt 5.0.0, this is an alias for Lwt_unix.recv_msg.

  • since 4.3.0
val send_msg_2 : + socket:file_descr -> + io_vectors:IO_vectors.t -> + fds:Unix.file_descr list -> + int Lwt.t

Since Lwt 5.0.0, this is an alias for Lwt_unix.send_msg.

  • since 4.3.0
diff --git a/dev/lwt/Lwt_unix/index.html b/dev/lwt/Lwt_unix/index.html new file mode 100644 index 00000000..164a39a2 --- /dev/null +++ b/dev/lwt/Lwt_unix/index.html @@ -0,0 +1,76 @@ + +Lwt_unix (lwt.Lwt_unix)

Module Lwt_unix

Cooperative system calls

This modules maps system calls, like those of the standard library's Unix module, to cooperative ones, which will not block the program.

The semantics of all operations is the following: if the action (for example reading from a file descriptor) can be performed immediately, it is performed and returns an already resolved promise, otherwise it returns a pending promise which is resolved when the operation completes.

Most operations on sockets and pipes (on Windows it is only sockets) are cancelable, meaning you can cancel them with Lwt.cancel. For example if you want to read something from a file descriptor with a timeout, you can cancel the action after the timeout and the reading will not be performed if not already done.

For example, consider that you have two sockets sock1 and sock2. You want to read something from sock1 or exclusively from sock2 and fail with an exception if a timeout of 1 second expires, without reading anything from sock1 and sock2, even if they become readable in the future.

Then you can do:

Lwt.pick
+  [Lwt_unix.timeout 1.0;
+   read sock1 buf1 ofs1 len1;
+   read sock2 buf2 ofs2 len2]

In this case, it is guaranteed that exactly one of the three operations will complete, and the others will be cancelled.

val handle_unix_error : ('a -> 'b Lwt.t) -> 'a -> 'b Lwt.t

Same as Unix.handle_unix_error but catches lwt-level exceptions

Sleeping

val sleep : float -> unit Lwt.t

sleep d is a promise that remains in a pending state for d seconds after which it is resolved with value ().

val yield : unit -> unit Lwt.t

yield () is a promise in a pending state. It resumes itself as soon as possible and resolves with value ().

  • deprecated

    Since 5.5.0 yield is deprecated. Use the more general Lwt.pause instead. See Lwt_main.yield for additional details.

val auto_yield : float -> unit -> unit Lwt.t
val auto_pause : float -> unit -> unit Lwt.t

auto_pause timeout returns a function f, and f () has the following behavior:

  • If it has been more than timeout seconds since the last time f () behaved like Lwt.pause, f () calls Lwt.pause.
  • Otherwise, if it has been less than timeout seconds, f () behaves like Lwt.return_unit, i.e. it does not yield.
exception Timeout

Exception raised by timeout operations

val timeout : float -> 'a Lwt.t

timeout d is a promise that remains pending for d seconds and then is rejected with Timeout.

  • raises Timeout

    The promise timeout d is rejected with Timeout unless it is cancelled.

val with_timeout : float -> (unit -> 'a Lwt.t) -> 'a Lwt.t

with_timeout d f is a short-hand for:

Lwt.pick [Lwt_unix.timeout d; f ()]
  • raises Timeout

    The promise with_timeout d f raises Timeout if the promise returned by f () takes more than d seconds to resolve.

Operations on file-descriptors

type file_descr

The abstract type for file descriptors. A Lwt file descriptor is a pair of a unix file descriptor (of type Unix.file_descr) and a state.

A file descriptor may be:

  • opened, in which case it is fully usable
  • closed or aborted, in which case it is no longer usable
type state =
  1. | Opened
    (*

    The file descriptor is opened

    *)
  2. | Closed
    (*

    The file descriptor has been closed by close. It must not be used for any operation.

    *)
  3. | Aborted of exn
    (*

    The file descriptor has been aborted, the only operation possible is close, all others will fail.

    *)

State of a file descriptor

val state : file_descr -> state

state fd returns the state of fd.

val unix_file_descr : file_descr -> Unix.file_descr

Returns the underlying unix file descriptor. It always succeeds, even if the file descriptor's state is not Opened.

val of_unix_file_descr : + ?blocking:bool -> + ?set_flags:bool -> + Unix.file_descr -> + file_descr

Wraps a Unix file descriptor fd in an Lwt file_descr fd'.

~blocking controls the internal strategy Lwt uses to perform I/O on the underlying fd. Regardless of ~blocking, at the API level, Lwt_unix.read, Lwt_unix.write, etc. on fd' always block the Lwt promise, but never block the whole process. However, for performance reasons, it is important that ~blocking match the actual blocking mode of fd.

If ~blocking is not specified, of_unix_file_descr chooses non-blocking mode for Unix sockets, Unix pipes, and Windows sockets, and blocking mode for everything else. Note: not specifying ~blocking causes fstat to be lazily called on fd, the first time your code performs I/O on fd'. This fstat call can be expensive, so if you use of_unix_file_descr a lot, be sure to specify ~blocking explicitly.

of_unix_file_descr runs a system call to set the specified or chosen blocking mode on the underlying fd.

To prevent of_unix_file_descr from running this system call, you can pass ~set_flags:false. Note that, in this case, if ~blocking, whether passed explicitly or chosen by Lwt, does not match the true blocking mode of the underlying fd, I/O on fd' will suffer performance degradation.

Note that ~set_flags is effectively always false if running on Windows and fd is not a socket.

Generally, non-blocking I/O is faster: for blocking I/O, Lwt typically has to run system calls in worker threads to avoid blocking the process. See your system documentation for whether particular kinds of file descriptors support non-blocking I/O.

val blocking : file_descr -> bool Lwt.t

blocking fd indicates whether Lwt is internally using blocking or non-blocking I/O with fd.

Note that this may differ from the blocking mode of the underlying Unix file descriptor (i.e. unix_file_descr fd).

See of_unix_file_descr for details.

val set_blocking : ?set_flags:bool -> file_descr -> bool -> unit

set_blocking fd b causes Lwt to internally use blocking or non-blocking I/O with fd, according to the value of b.

If ~set_flags is true (the default), Lwt also makes a system call to set the underlying file descriptor's blocking mode to match. Otherwise, set_blocking is only informational for Lwt.

It is important that the underlying file descriptor actually have the same blocking mode as that indicated by b.

See of_unix_file_descr for details.

val abort : file_descr -> exn -> unit

abort fd exn makes all current and further uses of the file descriptor fail with the given exception. This put the file descriptor into the Aborted state.

If the file descriptor is closed, this does nothing, if it is aborted, this replace the abort exception by exn.

Note that this only works for reading and writing operations on file descriptors supporting non-blocking mode.

Process handling

val fork : unit -> int

fork () does the same as Unix.fork. You must use this function instead of Unix.fork when you want to use Lwt in the child process, even if you have not started using Lwt before the fork.

Notes:

  • In the child process all pending Lwt_unix I/O jobs are abandoned. This may cause the child's copy of their associated promises to remain forever pending.
  • If you are going to use Lwt in the parent and the child, it is a good idea to call Lwt_io.flush_all before callling fork to avoid double-flush.
  • Otherwise, if you will not use Lwt in the child, call Lwt_main.Exit_hooks.remove_all to avoid Lwt calling Lwt_main.run during process exit.
  • None of the above is necessary if you intend to call exec. Indeed, in that case, it is not even necessary to use Lwt_unix.fork. You can use Unix.fork.
  • To abandon some more promises, see Lwt_main.abandon_yielded_and_paused.
type process_status = Unix.process_status =
  1. | WEXITED of int
  2. | WSIGNALED of int
  3. | WSTOPPED of int
type wait_flag = Unix.wait_flag =
  1. | WNOHANG
  2. | WUNTRACED
val wait : unit -> (int * process_status) Lwt.t

Wrapper for Unix.wait

val waitpid : wait_flag list -> int -> (int * process_status) Lwt.t

A promise-returning analog to Unix.waitpid. This call is non-blocking on Unix-like systems, but is always blocking on Windows.

type resource_usage = {
  1. ru_utime : float;
    (*

    User time used

    *)
  2. ru_stime : float;
    (*

    System time used

    *)
}

Resource usages

val wait4 : + wait_flag list -> + int -> + (int * process_status * resource_usage) Lwt.t

wait4 flags pid returns (pid, status, rusage) where (pid, status) is the same result as Unix.waitpid flags pid, and rusage contains accounting information about the child.

On windows it will always returns { utime = 0.0; stime = 0.0 }.

val wait_count : unit -> int

Returns the number of promises waiting for a child process to terminate.

val system : string -> process_status Lwt.t

Executes the given command, waits until it terminates, and return its termination status. The string is interpreted by the shell /bin/sh on Unix and cmd.exe on Windows. The result WEXITED 127 indicates that the shell couldn't be executed.

Basic file input/output

val stdin : file_descr

The file descriptor for standard input.

val stdout : file_descr

The file descriptor for standard output.

val stderr : file_descr

The file descriptor for standard error.

type file_perm = Unix.file_perm
type open_flag = Unix.open_flag =
  1. | O_RDONLY
  2. | O_WRONLY
  3. | O_RDWR
  4. | O_NONBLOCK
  5. | O_APPEND
  6. | O_CREAT
  7. | O_TRUNC
  8. | O_EXCL
  9. | O_NOCTTY
  10. | O_DSYNC
  11. | O_SYNC
  12. | O_RSYNC
  13. | O_SHARE_DELETE
  14. | O_CLOEXEC
  15. | O_KEEPEXEC
val openfile : string -> open_flag list -> file_perm -> file_descr Lwt.t

Wrapper for Unix.openfile.

val close : file_descr -> unit Lwt.t

Close a file descriptor. This close the underlying unix file descriptor and set its state to Closed.

val read : file_descr -> bytes -> int -> int -> int Lwt.t

read fd buf ofs len reads up to len bytes from fd, and writes them to buf, starting at offset ofs. The function immediately evaluates to an Lwt promise which waits for the operation to complete. If it completes successfully, the promise resolves to the number of bytes actually read, or zero if the end of file has been reached.

Note that the Lwt promise waits for data (or end of file) even if the underlying file descriptor is in non-blocking mode. See of_unix_file_descr for a discussion of non-blocking I/O and Lwt.

If Lwt is using blocking I/O on fd, read writes data into a temporary buffer, then copies it into buf.

The promise can be rejected with any exception that can be raised by Unix.read, except Unix.Unix_error Unix.EAGAIN, Unix.Unix_error Unix.EWOULDBLOCK or Unix.Unix_error Unix.EINTR.

val pread : file_descr -> bytes -> file_offset:int -> int -> int -> int Lwt.t

pread fd buf ~file_offset ofs len on file descriptors allowing seek, reads up to len bytes from fd at offset file_offset from the beginning of the file, and writes them to buf, starting at offset ofs.

On Unix systems, the file descriptor position is unaffected. On Windows it is changed to be just after the last read position.

The promise can be rejected with any exception that can be raised by read or lseek.

val write : file_descr -> bytes -> int -> int -> int Lwt.t

write fd buf ofs len writes up to len bytes to fd from buf, starting at buffer offset ofs. The function immediately evaluates to an Lwt promise which waits for the operation to complete. If the operation completes successfully, the promise resolves to the number of bytes actually written, which may be less than len.

Note that the Lwt promise waits to write even if the underlying file descriptor is in non-blocking mode. See of_unix_file_descr for a discussion of non-blocking I/O and Lwt.

If Lwt is using blocking I/O on fd, buf is copied before writing.

The promise can be rejected with any exception that can be raised by Unix.single_write, except Unix.Unix_error Unix.EAGAIN, Unix.Unix_error Unix.EWOULDBLOCK or Unix.Unix_error Unix.EINTR.

val pwrite : file_descr -> bytes -> file_offset:int -> int -> int -> int Lwt.t

pwrite fd buf ~file_offset ofs len on file descriptors allowing seek, writes up to len bytes to fd from buf, starting at buffer offset ofs. The data is written at offset file_offset from the beginning of fd.

On Unix systems, the file descriptor position is unaffected. On Windows it is changed to be just after the last written position.

The promise can be rejected with any exception that can be raised by write or lseek.

val write_string : file_descr -> string -> int -> int -> int Lwt.t

See write.

val pwrite_string : + file_descr -> + string -> + file_offset:int -> + int -> + int -> + int Lwt.t

See pwrite.

module IO_vectors : sig ... end

Sequences of buffer slices for writev.

val readv : file_descr -> IO_vectors.t -> int Lwt.t

readv fd vs reads bytes from fd into the buffer slices vs. If the operation completes successfully, the resulting promise resolves to the number of bytes read.

Data is always read directly into Bigarray slices. If the Unix file descriptor underlying fd is in non-blocking mode, data is also read directly into bytes slices. Otherwise, data for bytes slices is first read into temporary buffers, then copied.

Note that the returned Lwt promise is pending until failure or a successful read, even if the underlying file descriptor is in non-blocking mode. See of_unix_file_descr for a discussion of non-blocking I/O and Lwt.

If IO_vectors.system_limit is Some n and the count of slices in vs exceeds n, then Lwt_unix.readv reads only into the first n slices of vs.

Not implemented on Windows. It should be possible to implement, upon request, for Windows sockets only.

See readv(3p).

  • since 2.7.0
val writev : file_descr -> IO_vectors.t -> int Lwt.t

writev fd vs writes the bytes in the buffer slices vs to the file descriptor fd. If the operation completes successfully, the resulting promise resolves to the number of bytes written.

If the Unix file descriptor underlying fd is in non-blocking mode, writev does not make a copy the bytes before writing. Otherwise, it copies bytes slices, but not Bigarray slices.

Note that the returned Lwt promise is pending until failure or a successful write, even if the underlying descriptor is in non-blocking mode. See of_unix_file_descr for a discussion of non-blocking I/O and Lwt.

If IO_vectors.system_limit is Some n and the count of slices in vs exceeds n, then Lwt_unix.writev passes only the first n slices in vs to the underlying writev system call.

Not implemented on Windows. It should be possible to implement, upon request, for Windows sockets only.

The behavior of writev when vs has zero slices depends on the system, and may change in future versions of Lwt. On Linux, writev will succeed and write zero bytes. On BSD (including macOS), writev will fail with Unix.Unix_error (Unix.EINVAL, "writev", ...).

See writev(3p).

  • since 2.7.0
val readable : file_descr -> bool

Returns whether the given file descriptor is currently readable.

val writable : file_descr -> bool

Returns whether the given file descriptor is currently writable.

val wait_read : file_descr -> unit Lwt.t

Waits (without blocking other promises) until there is something to read from the file descriptor.

Note that you don't need to use this function if you are using Lwt I/O functions for reading, since they provide non-blocking waiting automatically.

The intended use case for this function is interfacing with existing libraries that are known to be blocking.

val wait_write : file_descr -> unit Lwt.t

Waits (without blocking other promises) until it is possible to write on the file descriptor.

Note that you don't need to use this function if you are using Lwt I/O functions for writing, since they provide non-blocking waiting automatically.

The intended use case for this function is interfacing with existing libraries that are known to be blocking.

Seeking and truncating

type seek_command = Unix.seek_command =
  1. | SEEK_SET
  2. | SEEK_CUR
  3. | SEEK_END
val lseek : file_descr -> int -> seek_command -> int Lwt.t

Wrapper for Unix.lseek

val truncate : string -> int -> unit Lwt.t

Wrapper for Unix.truncate

val ftruncate : file_descr -> int -> unit Lwt.t

Wrapper for Unix.ftruncate

Syncing

val fsync : file_descr -> unit Lwt.t

Synchronise all data and metadata of the file descriptor with the disk. On Windows it uses FlushFileBuffers.

val fdatasync : file_descr -> unit Lwt.t

Synchronise all data (but not metadata) of the file descriptor with the disk.

Note that fdatasync is not available on Windows and OS X.

File status

type file_kind = Unix.file_kind =
  1. | S_REG
  2. | S_DIR
  3. | S_CHR
  4. | S_BLK
  5. | S_LNK
  6. | S_FIFO
  7. | S_SOCK
type stats = Unix.stats = {
  1. st_dev : int;
  2. st_ino : int;
  3. st_kind : file_kind;
  4. st_perm : file_perm;
  5. st_uid : int;
  6. st_gid : int;
  7. st_rdev : int;
  8. st_size : int;
  9. st_atime : float;
  10. st_mtime : float;
  11. st_ctime : float;
}
val stat : string -> stats Lwt.t

Wrapper for Unix.stat

val lstat : string -> stats Lwt.t

Wrapper for Unix.lstat

val fstat : file_descr -> stats Lwt.t

Wrapper for Unix.fstat

val file_exists : string -> bool Lwt.t

file_exists name tests if a file named name exists.

Note that file_exists behaves similarly to Sys.file_exists:

  • β€œfile” is interpreted as β€œdirectory entry” in this context
  • file_exists name will return false in circumstances that would make stat raise a Unix.Unix_error exception.
val utimes : string -> float -> float -> unit Lwt.t

utimes path atime mtime updates the access and modification times of the file at path. The access time is set to atime and the modification time to mtime. To set both to the current time, call utimes path 0. 0..

This function corresponds to Unix.utimes. See also utimes(3p).

  • since 2.6.0
val isatty : file_descr -> bool Lwt.t

Wrapper for Unix.isatty

File operations on large files

module LargeFile : sig ... end

Operations on file names

Wrapper for Unix.unlink

val rename : string -> string -> unit Lwt.t

Wrapper for Unix.rename

Wrapper for Unix.link

File permissions and ownership

val chmod : string -> file_perm -> unit Lwt.t

Wrapper for Unix.chmod

val fchmod : file_descr -> file_perm -> unit Lwt.t

Wrapper for Unix.fchmod

val chown : string -> int -> int -> unit Lwt.t

Wrapper for Unix.chown

val fchown : file_descr -> int -> int -> unit Lwt.t

Wrapper for Unix.fchown

type access_permission = Unix.access_permission =
  1. | R_OK
  2. | W_OK
  3. | X_OK
  4. | F_OK
val access : string -> access_permission list -> unit Lwt.t

Wrapper for Unix.access

Operations on file descriptors

val dup : ?cloexec:bool -> file_descr -> file_descr

Wrapper for Unix.dup

val dup2 : ?cloexec:bool -> file_descr -> file_descr -> unit

Wrapper for Unix.dup2

val set_close_on_exec : file_descr -> unit
val clear_close_on_exec : file_descr -> unit

Directories

val mkdir : string -> file_perm -> unit Lwt.t

Wrapper for Unix.mkdir

val rmdir : string -> unit Lwt.t

Wrapper for Unix.rmdir

val chdir : string -> unit Lwt.t

Wrapper for Unix.chdir

val getcwd : unit -> string Lwt.t

Wrapper for Unix.getcwd

  • since 3.1.0
val chroot : string -> unit Lwt.t

Wrapper for Unix.chroot

type dir_handle = Unix.dir_handle
val opendir : string -> dir_handle Lwt.t

Opens a directory for listing. Directories opened with this function must be explicitly closed with closedir. This is a cooperative analog of Unix.opendir.

val readdir : dir_handle -> string Lwt.t

Reads the next directory entry from the given directory. Special entries such as . and .. are included. If all entries have been read, raises End_of_file. This is a cooperative analog of Unix.readdir.

val readdir_n : dir_handle -> int -> string array Lwt.t

readdir_n handle count reads at most count entries from the given directory. It is more efficient than calling readdir count times. If the length of the returned array is smaller than count, this means that the end of the directory has been reached.

val rewinddir : dir_handle -> unit Lwt.t

Resets the given directory handle, so that directory listing can be restarted. Cooperative analog of Unix.rewinddir.

val closedir : dir_handle -> unit Lwt.t

Closes a directory handle. Cooperative analog of Unix.closedir.

val files_of_directory : string -> string Lwt_stream.t

files_of_directory dir returns the stream of all files of dir.

Pipes and redirections

val pipe : ?cloexec:bool -> unit -> file_descr * file_descr

pipe () creates pipe using Unix.pipe and returns two lwt file descriptors created from unix file_descriptor

val pipe_in : ?cloexec:bool -> unit -> file_descr * Unix.file_descr

pipe_in () is the same as pipe but maps only the unix file descriptor for reading into a lwt one. The second is not put into non-blocking mode. You usually want to use this before forking to receive data from the child process.

val pipe_out : ?cloexec:bool -> unit -> Unix.file_descr * file_descr

pipe_out () is the inverse of pipe_in. You usually want to use this before forking to send data to the child process

val mkfifo : string -> file_perm -> unit Lwt.t

Wrapper for Unix.mkfifo

Wrapper for Unix.symlink

Wrapper for Unix.readlink

Locking

type lock_command = Unix.lock_command =
  1. | F_ULOCK
  2. | F_LOCK
  3. | F_TLOCK
  4. | F_TEST
  5. | F_RLOCK
  6. | F_TRLOCK
val lockf : file_descr -> lock_command -> int -> unit Lwt.t

Wrapper for Unix.lockf

User id, group id

type passwd_entry = Unix.passwd_entry = {
  1. pw_name : string;
  2. pw_passwd : string;
  3. pw_uid : int;
  4. pw_gid : int;
  5. pw_gecos : string;
  6. pw_dir : string;
  7. pw_shell : string;
}
type group_entry = Unix.group_entry = {
  1. gr_name : string;
  2. gr_passwd : string;
  3. gr_gid : int;
  4. gr_mem : string array;
}
val getlogin : unit -> string Lwt.t

Wrapper for Unix.getlogin

val getpwnam : string -> passwd_entry Lwt.t

Wrapper for Unix.getpwnam

val getgrnam : string -> group_entry Lwt.t

Wrapper for Unix.getgrnam

val getpwuid : int -> passwd_entry Lwt.t

Wrapper for Unix.getpwuid

val getgrgid : int -> group_entry Lwt.t

Wrapper for Unix.getgrgid

Signals

type signal_handler_id

Id of a signal handler, used to cancel it

val on_signal : int -> (int -> unit) -> signal_handler_id

on_signal signum f calls f each time the signal with numnber signum is received by the process. It returns a signal handler identifier that can be used to stop monitoring signum.

val on_signal_full : + int -> + (signal_handler_id -> int -> unit) -> + signal_handler_id

on_signal_full f is the same as on_signal f except that f also receive the signal handler identifier as argument so it can disable it.

val disable_signal_handler : signal_handler_id -> unit

Stops receiving this signal

val signal_count : unit -> int

Returns the number of registered signal handler.

val reinstall_signal_handler : int -> unit

reinstall_signal_handler signum if any signal handler is registered for this signal with on_signal, it reinstall the signal handler (with Sys.set_signal). This is useful in case another part of the program install another signal handler.

val handle_signal : int -> unit

handle_signal signum acts as if Lwt had received the signum signal. This allows another IO library to install the handler, perform its own handling, but still notify Lwt. It is particularly useful for SIGCHLD, where several IO libraries may be spawning sub-processes.

This function is thread-safe.

Sockets

type inet_addr = Unix.inet_addr
type socket_domain = Unix.socket_domain =
  1. | PF_UNIX
  2. | PF_INET
  3. | PF_INET6
type socket_type = Unix.socket_type =
  1. | SOCK_STREAM
  2. | SOCK_DGRAM
  3. | SOCK_RAW
  4. | SOCK_SEQPACKET
type sockaddr = Unix.sockaddr =
  1. | ADDR_UNIX of string
  2. | ADDR_INET of inet_addr * int
val socket : ?cloexec:bool -> socket_domain -> socket_type -> int -> file_descr

socket domain type proto is the same as Unix.socket but maps the result into a lwt file descriptor

val socketpair : + ?cloexec:bool -> + socket_domain -> + socket_type -> + int -> + file_descr * file_descr

Wrapper for Unix.socketpair

val bind : file_descr -> sockaddr -> unit Lwt.t

Binds an address to the given socket. This is the cooperative analog of Unix.bind. See also bind(3p).

  • since 3.0.0
val listen : file_descr -> int -> unit

Wrapper for Unix.listen

val accept : ?cloexec:bool -> file_descr -> (file_descr * sockaddr) Lwt.t

Wrapper for Unix.accept

val accept_n : + ?cloexec:bool -> + file_descr -> + int -> + ((file_descr * sockaddr) list * exn option) Lwt.t

accept_n fd count accepts up to count connections at one time.

  • if no connection is available right now, it returns a pending promise
  • if more than 1 and less than count are available, it returns all of them
  • if more than count are available, it returns the next count of them
  • if an error happens, it returns the connections that have been successfully accepted so far and the error

accept_n has the advantage of improving performance. If you want a more detailed description, you can have a look at:

Acceptable strategies for improving web server performance

val connect : file_descr -> sockaddr -> unit Lwt.t

Wrapper for Unix.connect

type shutdown_command = Unix.shutdown_command =
  1. | SHUTDOWN_RECEIVE
  2. | SHUTDOWN_SEND
  3. | SHUTDOWN_ALL
val shutdown : file_descr -> shutdown_command -> unit

Wrapper for Unix.shutdown

val getsockname : file_descr -> sockaddr

Wrapper for Unix.getsockname

val getpeername : file_descr -> sockaddr

Wrapper for Unix.getpeername

type msg_flag = Unix.msg_flag =
  1. | MSG_OOB
  2. | MSG_DONTROUTE
  3. | MSG_PEEK
val recv : file_descr -> bytes -> int -> int -> msg_flag list -> int Lwt.t

Wrapper for Unix.recv.

On Windows, recv writes data into a temporary buffer, then copies it into the given one.

val recvfrom : + file_descr -> + bytes -> + int -> + int -> + msg_flag list -> + (int * sockaddr) Lwt.t

Wrapper for Unix.recvfrom.

On Windows, recvfrom writes data into a temporary buffer, then copies it into the given one.

val send : file_descr -> bytes -> int -> int -> msg_flag list -> int Lwt.t

Wrapper for Unix.send.

On Windows, send copies the given buffer before writing.

val sendto : + file_descr -> + bytes -> + int -> + int -> + msg_flag list -> + sockaddr -> + int Lwt.t

Wrapper for Unix.sendto.

On Windows, sendto copies the given buffer before writing.

val recv_msg : + socket:file_descr -> + io_vectors:IO_vectors.t -> + (int * Unix.file_descr list) Lwt.t

recv_msg ~socket ~io_vectors receives data into a list of io-vectors, plus any file-descriptors that may accompany the messages. It returns a tuple whose first field is the number of bytes received and second is a list of received file descriptors. The messages themselves will be recorded in the provided io_vectors list. Data is written directly into the iov_buffer buffers.

Not implemented on Windows.

  • since 5.0.0
val send_msg : + socket:file_descr -> + io_vectors:IO_vectors.t -> + fds:Unix.file_descr list -> + int Lwt.t

send_msg ~socket ~io_vectors ~fds sends data from a list of io-vectors, accompanied with a list of file-descriptors. It returns the number of bytes sent. If fd-passing is not possible on the current system and fds is not empty, it raises Lwt_sys.Not_available "fd_passing". Data is written directly from the io_vectors buffers.

Not implemented on Windows.

  • since 5.0.0
val send_msgto : + socket:file_descr -> + io_vectors:IO_vectors.t -> + fds:Unix.file_descr list -> + dest:Unix.sockaddr -> + int Lwt.t

send_msgto ~socket ~io_vectors ~fds ~dest is similar to send_msg but takes an additional dest argument to set the address when using a connection-less socket.

Not implemented on Windows.

  • since 5.4.0
type credentials = {
  1. cred_pid : int;
  2. cred_uid : int;
  3. cred_gid : int;
}
val get_credentials : file_descr -> credentials

get_credentials fd returns credentials information from the given socket. On some platforms, obtaining the peer pid is not possible and it will be set to -1. If obtaining credentials is not possible on the current system, it raises Lwt_sys.Not_available "get_credentials".

This call is not available on windows.

Socket options

type socket_bool_option = Unix.socket_bool_option =
  1. | SO_DEBUG
  2. | SO_BROADCAST
  3. | SO_REUSEADDR
  4. | SO_KEEPALIVE
  5. | SO_DONTROUTE
  6. | SO_OOBINLINE
  7. | SO_ACCEPTCONN
  8. | TCP_NODELAY
  9. | IPV6_ONLY
  10. | SO_REUSEPORT
type socket_int_option = Unix.socket_int_option =
  1. | SO_SNDBUF
  2. | SO_RCVBUF
  3. | SO_ERROR
    (*
    • deprecated Use Unix.getsockopt_error instead.
    *)
  4. | SO_TYPE
  5. | SO_RCVLOWAT
  6. | SO_SNDLOWAT
type socket_optint_option = Unix.socket_optint_option =
  1. | SO_LINGER
type socket_float_option = Unix.socket_float_option =
  1. | SO_RCVTIMEO
  2. | SO_SNDTIMEO
    (*

    Note: these options are provided for the sake of completeness only. Lwt places all sockets in non-blocking mode, for which these options are meaningless. Use Lwt.pick with Lwt_unix.sleep or Lwt_unix.timeout for timeouts.

    *)
val getsockopt : file_descr -> socket_bool_option -> bool

Wrapper for Unix.getsockopt

val setsockopt : file_descr -> socket_bool_option -> bool -> unit

Wrapper for Unix.setsockopt

val getsockopt_int : file_descr -> socket_int_option -> int
val setsockopt_int : file_descr -> socket_int_option -> int -> unit
val getsockopt_optint : file_descr -> socket_optint_option -> int option
val setsockopt_optint : + file_descr -> + socket_optint_option -> + int option -> + unit
val getsockopt_float : file_descr -> socket_float_option -> float
val setsockopt_float : file_descr -> socket_float_option -> float -> unit
val getsockopt_error : file_descr -> Unix.error option

Multicast functions

val mcast_set_loop : file_descr -> bool -> unit

Whether sent multicast messages are received by the sending host

val mcast_set_ttl : file_descr -> int -> unit

Set TTL/hops value

val mcast_add_membership : + file_descr -> + ?ifname:Unix.inet_addr -> + Unix.inet_addr -> + unit

mcast_add_membership fd ~ifname addr joins the multicast group addr on the network interface ifname.

val mcast_drop_membership : + file_descr -> + ?ifname:Unix.inet_addr -> + Unix.inet_addr -> + unit

mcast_drop_membership fd ~ifname addr leaves the multicast group addr on the network interface ifname.

Host and protocol databases

type host_entry = Unix.host_entry = {
  1. h_name : string;
  2. h_aliases : string array;
  3. h_addrtype : socket_domain;
  4. h_addr_list : inet_addr array;
}
type protocol_entry = Unix.protocol_entry = {
  1. p_name : string;
  2. p_aliases : string array;
  3. p_proto : int;
}
type service_entry = Unix.service_entry = {
  1. s_name : string;
  2. s_aliases : string array;
  3. s_port : int;
  4. s_proto : string;
}
val gethostname : unit -> string Lwt.t

Wrapper for Unix.gethostname

val gethostbyname : string -> host_entry Lwt.t

Wrapper for Unix.gethostbyname

val gethostbyaddr : inet_addr -> host_entry Lwt.t

Wrapper for Unix.gethostbyaddr

val getprotobyname : string -> protocol_entry Lwt.t
val getprotobynumber : int -> protocol_entry Lwt.t
val getservbyname : string -> string -> service_entry Lwt.t

Wrapper for Unix.getservbyname

val getservbyport : int -> string -> service_entry Lwt.t

Wrapper for Unix.getservbyport

type addr_info = Unix.addr_info = {
  1. ai_family : socket_domain;
  2. ai_socktype : socket_type;
  3. ai_protocol : int;
  4. ai_addr : sockaddr;
  5. ai_canonname : string;
}
type getaddrinfo_option = Unix.getaddrinfo_option =
  1. | AI_FAMILY of socket_domain
  2. | AI_SOCKTYPE of socket_type
  3. | AI_PROTOCOL of int
  4. | AI_NUMERICHOST
  5. | AI_CANONNAME
  6. | AI_PASSIVE
val getaddrinfo : + string -> + string -> + getaddrinfo_option list -> + addr_info list Lwt.t

Wrapper for Unix.getaddrinfo

type name_info = Unix.name_info = {
  1. ni_hostname : string;
  2. ni_service : string;
}
type getnameinfo_option = Unix.getnameinfo_option =
  1. | NI_NOFQDN
  2. | NI_NUMERICHOST
  3. | NI_NAMEREQD
  4. | NI_NUMERICSERV
  5. | NI_DGRAM
val getnameinfo : sockaddr -> getnameinfo_option list -> name_info Lwt.t

Wrapper for Unix.getnameinfo

Terminal interface

type terminal_io = Unix.terminal_io = {
  1. mutable c_ignbrk : bool;
  2. mutable c_brkint : bool;
  3. mutable c_ignpar : bool;
  4. mutable c_parmrk : bool;
  5. mutable c_inpck : bool;
  6. mutable c_istrip : bool;
  7. mutable c_inlcr : bool;
  8. mutable c_igncr : bool;
  9. mutable c_icrnl : bool;
  10. mutable c_ixon : bool;
  11. mutable c_ixoff : bool;
  12. mutable c_opost : bool;
  13. mutable c_obaud : int;
  14. mutable c_ibaud : int;
  15. mutable c_csize : int;
  16. mutable c_cstopb : int;
  17. mutable c_cread : bool;
  18. mutable c_parenb : bool;
  19. mutable c_parodd : bool;
  20. mutable c_hupcl : bool;
  21. mutable c_clocal : bool;
  22. mutable c_isig : bool;
  23. mutable c_icanon : bool;
  24. mutable c_noflsh : bool;
  25. mutable c_echo : bool;
  26. mutable c_echoe : bool;
  27. mutable c_echok : bool;
  28. mutable c_echonl : bool;
  29. mutable c_vintr : char;
  30. mutable c_vquit : char;
  31. mutable c_verase : char;
  32. mutable c_vkill : char;
  33. mutable c_veof : char;
  34. mutable c_veol : char;
  35. mutable c_vmin : int;
  36. mutable c_vtime : int;
  37. mutable c_vstart : char;
  38. mutable c_vstop : char;
}
val tcgetattr : file_descr -> terminal_io Lwt.t

Wrapper for Unix.tcgetattr

type setattr_when = Unix.setattr_when =
  1. | TCSANOW
  2. | TCSADRAIN
  3. | TCSAFLUSH
val tcsetattr : file_descr -> setattr_when -> terminal_io -> unit Lwt.t

Wrapper for Unix.tcsetattr

val tcsendbreak : file_descr -> int -> unit Lwt.t

Wrapper for Unix.tcsendbreak

val tcdrain : file_descr -> unit Lwt.t

Wrapper for Unix.tcdrain

type flush_queue = Unix.flush_queue =
  1. | TCIFLUSH
  2. | TCOFLUSH
  3. | TCIOFLUSH
val tcflush : file_descr -> flush_queue -> unit Lwt.t

Wrapper for Unix.tcflush

type flow_action = Unix.flow_action =
  1. | TCOOFF
  2. | TCOON
  3. | TCIOFF
  4. | TCION
val tcflow : file_descr -> flow_action -> unit Lwt.t

Wrapper for Unix.tcflow

Configuration (deprecated)

type async_method =
  1. | Async_none
    (*

    System calls are made synchronously, and may block the entire program.

    *)
  2. | Async_detach
    (*

    System calls are made in another system thread, thus without blocking other Lwt promises. The drawback is that it may degrade performance in some cases.

    This is the default.

    *)
  3. | Async_switch
    (*
    • deprecated

      A synonym for Async_detach. This was a different method in the past.

    *)

For system calls that cannot be made asynchronously, Lwt uses one of the following method:

val default_async_method : unit -> async_method

Returns the default async method.

This can be initialized using the environment variable "LWT_ASYNC_METHOD" with possible values "none", "detach" and "switch".

  • deprecated

    Will always return Async_detach in Lwt 5.0.0.

val set_default_async_method : async_method -> unit

Sets the default async method.

  • deprecated

    Will be a no-op in Lwt 5.0.0.

val async_method : unit -> async_method

async_method () returns the async method used in the current thread.

  • deprecated

    Will always return Async_detach in Lwt 5.0.0.

val async_method_key : async_method Lwt.key

The key for storing the local async method.

  • deprecated

    Will be ignored in Lwt 5.0.0.

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

with_async_none f is a shorthand for:

Lwt.with_value async_method_key (Some Async_none) f
  • deprecated

    Will have no effect in Lwt 5.0.0.

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

with_async_detach f is a shorthand for:

Lwt.with_value async_method_key (Some Async_detach) f
  • deprecated

    Will have no effect in Lwt 5.0.0.

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

with_async_switch f is a shorthand for:

Lwt.with_value async_method_key (Some Async_switch) f
  • deprecated

    Will have no effect in Lwt 5.0.0.

Low-level interaction

exception Retry

If an action raises Retry, it will be requeued until the file descriptor becomes readable/writable again.

exception Retry_read

If an action raises Retry_read, it will be requeued until the file descriptor becomes readable.

exception Retry_write

If an action raises Retry_read, it will be requeued until the file descriptor becomes writables.

type io_event =
  1. | Read
  2. | Write
val wrap_syscall : io_event -> file_descr -> (unit -> 'a) -> 'a Lwt.t

wrap_syscall set fd action wrap an action on a file descriptor. It tries to execute action, and if it can not be performed immediately without blocking, it is registered for later.

In the latter case, if the promise is canceled, action is removed from set.

val check_descriptor : file_descr -> unit

check_descriptor fd raise an exception if fd is not in the state Open.

val register_action : io_event -> file_descr -> (unit -> 'a) -> 'a Lwt.t

register_action set fd action registers action on fd. When fd becomes readable/writable action is called.

Note:

  • you must call check_descriptor fd before calling register_action
type 'a job

Type of job descriptions. A job description describe how to call a C function and how to get its result. The C function may be executed in another system thread.

val run_job : ?async_method:async_method -> 'a job -> 'a Lwt.t

run_job ?async_method job starts job and wait for its termination.

The ~async_method argument will be ignored in Lwt 5.0.0, and this function will always act as if ~async_method:Async_detach is passed.

The async method is chosen follow:

  • if the optional parameter async_method is specified, it is used,
  • otherwise if the local key async_method_key is set in the current thread, it is used,
  • otherwise the default method (returned by default_async_method) is used.

If the method is Async_none then the job is run synchronously and may block the current system thread, thus blocking all Lwt threads.

If the method is Async_detach then the job is run in another system thread, unless the the maximum number of worker threads has been reached (as given by pool_size).

If the method is Async_switch then the job is run synchronously and if it blocks, execution will continue in another system thread (unless the limit is reached).

val abort_jobs : exn -> unit

abort_jobs exn make all pending jobs to fail with exn. Note that this does not abort the real job (i.e. the C function executing it), just the lwt thread for it.

val cancel_jobs : unit -> unit

cancel_jobs () is the same as abort_jobs Lwt.Canceled.

val wait_for_jobs : unit -> unit Lwt.t

Wait for all pending jobs to terminate.

val execute_job : + ?async_method:async_method -> + job:'a job -> + result:('a job -> 'b) -> + free:('a job -> unit) -> + 'b Lwt.t
  • deprecated

    Use run_job.

Notifications

Lwt internally use a pipe to send notification to the main thread. The following functions allow to use this pipe.

val make_notification : ?once:bool -> (unit -> unit) -> int

make_notification ?once f registers a new notifier. It returns the id of the notifier. Each time a notification with this id is received, f is called.

if once is specified, then the notification is stopped after the first time it is received. It defaults to false.

val send_notification : int -> unit

send_notification id sends a notification.

This function is thread-safe.

val stop_notification : int -> unit

Stop the given notification. Note that you should not reuse the id after the notification has been stopped, the result is unspecified if you do so.

val call_notification : int -> unit

Call the handler associated to the given notification. Note that if the notification was defined with once = true it is removed.

val set_notification : int -> (unit -> unit) -> unit

set_notification id f replace the function associated to the notification by f. It raises Not_found if the given notification is not found.

System threads pool

If the program is using the async method Async_detach or Async_switch, Lwt will launch system threads to execute blocking system calls asynchronously.

val pool_size : unit -> int

Maximum number of system threads that can be started. If this limit is reached, jobs will be executed synchronously.

val set_pool_size : int -> unit

Change the size of the pool.

val thread_count : unit -> int

The number of system threads running (excluding this one).

val thread_waiting_count : unit -> int

The number threads waiting for a job.

CPUs

val get_cpu : unit -> int

get_cpu () returns the number of the CPU the current thread is running on.

val get_affinity : ?pid:int -> unit -> int list

get_affinity ?pid () returns the list of CPUs the process with pid pid is allowed to run on. If pid is not specified then the affinity of the current process is returned.

val set_affinity : ?pid:int -> int list -> unit

set_affinity ?pid cpus sets the list of CPUs the given process is allowed to run on.

Versioned interfaces

module Versioned : sig ... end

Versioned variants of APIs undergoing breaking changes.

diff --git a/dev/lwt/_doc-dir/CHANGES b/dev/lwt/_doc-dir/CHANGES new file mode 100644 index 00000000..02f2e473 --- /dev/null +++ b/dev/lwt/_doc-dir/CHANGES @@ -0,0 +1,1145 @@ +===== 5.7.0 ===== + +====== Breaking API changes ====== + + * Lwt_result.catch now takes a function (unit -> 'a t) rather than a promise ('a t). (#965) + + * Remove the deprecated Lwt.result type (use Stdlib.result instead). (#968) + + * Remove the deprecated Lwt.make_value and Lwt.make_result functions (use Ok and Error instead). (#968) + + * Remove the deprecated and unsafe waiter_of_wakener (keep the waiter around when you create the wakener instead). (#968) + + * Remove the deprecated Lwt_stream.on_termination and Lwt_stream.on_terminate (bind to Lwt_stream.closed instead). (#968) + + * Remove the deprecated Lwt_stream.result type (use Stdlib.result instead). (#968) + + * Remove the deprecated Lwt_stream.map_exn function (use wrap_exn instead). (#968) + +====== Additions ====== + + * Lwt.Exception_filter for enabling/disabling system-exception catching. (#964) + + * Lwt.reraise an exception raising function which preserves backtraces, recommended for use in Lwt.catch. (#963) + + * Expose Lwt_io.delete_recursively for deleting a directory and its content recursively. (#984, Antonin DΓ©cimo) + + * Lwt_preemptive.run_in_main_dont_wait to run a function in the main preemptive thread but without waiting for the result. (Kate Deplaix, #960) + + * Lwt_unix.handle_signal and Lwt_engine.forwards_signal to allow other IO libraries (such as Eio) to share signal handlers. (Thomas Leonard, #993, #991) + +====== Build ====== + + * Remove unused dependency in dune file. (#969, Kate Deplaix) + + * Fix some compilation warnings for C stubs with OCaml 5. (#976, Antonin DΓ©cimo) + +====== Fixes ====== + + * Use SA_ONSTACK on OCaml5 to avoid SIGSEGV. (Thomas Leonard, #993, #981) + + * Fix race in worker loop. (Thomas Leonard, #993, #994) + + * Fix marshall header size in Lwt_io.read_value. (Simmo Saan, #995) + +====== Misc ====== + + * Resolve paused promises only once in main loop. This lets Lwt.pause behave identical to Lwt_unix.yield. (#917, Christopher Zimmermann, Favonia) + + +===== 5.6.1 ===== + +====== Fixes ====== + + * Fix null file descriptor being closed when used as redirection for standard fd of child processes. (#957, Antonin DΓ©cimo) + +===== 5.6.0 ===== + +====== Installability ====== + + * Lwt is now compatible with OCaml 5.00. Lwt is now incompatible with OCaml 4.02. (#925, #923, Kate Deplaix, Patrick Ferris) + * Lwt is now incompatible with OCaml.4.07 and earlier. (#947, Hannes Mehnert, Tim McGilchrist) + * Lwt-unix is now compatible with OCaml 5.0.0. (#953, David Allsopp) + +====== Additions ====== + + * In the Lwt_io module, add `?cloexec:bool` optional arguments to functions that create file descriptors (`pipe`). The `?cloexec` argument is simply forwarded to the wrapped Lwt_unix function. (#872, #911, Antonin DΓ©cimo) + * Add Lwt_result.error, Lwt_result.iter, and Lwt_result.iter_error for consistency with Stdlib. (#927, Antonin DΓ©cimo) + * Lwt_result.bind_error. (#943, Boning Dong) + * Add ?cloexec parameter to Lwt_io.pipe. (#911, Antonin DΓ©cimo) + +====== Misc ====== + + * On Windows, make Lwt_process.create_process duplicate standard handles given to the child process if they're not inheritable, to mimic the behaviour of Unix.create_process. (#909, Antonin DΓ©cimo) + * Add missing dependency to `cppo` in lwt-react's opam file. (#946, Rizo I) + * Improve documentation (especially internal links). (#928, Antonin DΓ©cimo) + * Fix documentation of infix choose. (#952, Reynir BjΓΆrnsson) + * Only define OCAML_NAME_SPACE for OCaml<5.0.0. (#929, Antonin DΓ©cimo) + * Replace mentions of Pervasives with Stdlib in the doc. (#954, Antonin DΓ©cimo) + * Improve deprecation message for auto_yield. (#908, Seb Mondet) + * Fix mirage tutorial link. (#936, Tuomas Lukka) + * Fix issues in opam file. (#937, Andreas Hauptmann) + +====== Fixes ====== + + * Fix win32_spawn leaking dev_null fd in the parent process. (#906, Antonin DΓ©cimo) + * Prefer SetHandleInformation to DuplicateHandle in set_close_on_exec for sockets. DuplicateHandle mustn't be used on sockets. (#907, Antonin DΓ©cimo) + * Lwt.pick and Lwt.choose select preferentially failed promises as per documentation (#856, #874, Raman Varabets) + * Use the WSA_FLAG_NO_HANDLE_INHERIT on Windows when creating sockets with WSASocket if the cloexec (non-inheritable) parameter is true. Fixes a Windows problem where a child process would inherit a supposedly non-inheritable socket. (#910, Antonin DΓ©cimo) + * Fix macOS/arm64 tests which have a 16k page. (#932, Kate Deplaix) + * Fix Lwt_unix.closedir incorrectly checking the return value of closedir(3). (#942, Antonin DΓ©cimo) + * Fix custom_operations struct not fully initialized after OCaml 4.08. (Antonin DΓ©cimo, #918) + * Fix missing include directive. (#940, Antonin DΓ©cimo) + * Fix missing initialisation in Unix stub. (#941, Antonin DΓ©cimo) + +====== Deprecations ====== + + * Alias Lwt_result.map_err and Lwt_result.bind_lwt_err to Lwt_result.map_error and Lwt_result.bind_lwt_error for consistency with Stdlib. (#927, Antonin DΓ©cimo) + +===== 5.5.0 ===== + +====== Deprecations ====== + + * Lwt_main.yield and Lwt_unix.yield are deprecated in favor of the generic Lwt.pause, and Lwt_unix.auto_yield is deprecated in favor of the new Lwt_unix.auto_pause. Currently, Lwt_main.run resolves paused promises more frequently than yielded promises; the difference is unintended but existing applications could unintentionally depend on it. (#855, #858, Favonia) + +====== Fixes ====== + + * Use is_blocking in dup and dup2 to fix ENOTSOCK on Windows. (#869, Antonin DΓ©cimo) + + * Lwt_unix.lstat was incorrectly calling Unix.stat on Win32. Fixes the behavior of Lwt_io.with_temp_dir following symlinks to directories on Win32. (#883, Antonin DΓ©cimo) + + * Support deleting symlinks on Windows during cleanup of Lwt_io.with_temp_dir. (#886, Antonin DΓ©cimo) + + * Lwt_react.S.l[2-6]_s used polymorphic equality which could cause errors when handling functional values. (#893, JΓ©rΓ΄me Vouillon) + + * On Windows, treat ERROR_BROKEN_PIPE on read as zero-read instead of error. See OCaml PR #4790. (#898, Antonin DΓ©cimo) + + * Fix compilation under MSVC by replacing Noreturn with CAMLnoreturn. (#880, #887, NicolΓ‘s Ojeda BΓ€r) + +====== Additions ====== + + * Lwt_bytes.blit_from_string: string complement of Lwt_bytes.blit. (#882, Hugo Heuzard) + + * Lwt_seq: a Seq-like data-structure with Lwt delayed nodes. (#836, #842, Zach Shipko) + + * Lwt_unix.auto_pause: the replacement of Lwt_unix.auto_yield that uses Lwt.pause instead of Lwt_unix.yield. (#855, #858, Favonia) + + * Lwt_stream.return, Lwt_stream.return_lwt: singleton stream constructors. (#864, Boning Dong) + + * Add ?to_dir param from Unix.symlink to Lwt_unix.symlink wrapper. (#884, Antonin DΓ©cimo) + + * Lwt_stream.of_lwt_seq to convert an Lwt-sequence into an Lwt-stream. (#873) + + * Support IPv6 (always) and PF_UNIX (with OCaml >= 4.14) socketpair on Windows. (#870, #876, Antonin DΓ©cimo, David Allsopp) + + * In the Lwt_unix module, add `?cloexec:bool` optional arguments to functions that create file descriptors (`dup`, `dup2`, `pipe`, `pipe_in`, `pipe_out`, `socket`, `socketpair`, `accept`, `accept_n`). The `?cloexec` argument is simply forwarded to the wrapped Unix function (with OCaml >= 4.05, see PR ocaml/ocaml#650), or emulated as best-effort with `Unix.set_close_on_exec` on older OCaml versions. (#327, #847, #872, #901, Antonin DΓ©cimo) + + * Lwt_domain: helpers for using domainslib from Lwt. (#860, Sudha Parimala) + +====== Misc ====== + + * Code quality improvement: remove an unneeded Obj.magic. (#844, Benoit Montagu) + + * On Windows, use the Unicode API in C stubs and functions introduced in OCaml 4.06 to handle Unicode strings. Raise the minimum requirement to OCaml 4.06 (on Windows only). (#843, #903, Antonin DΓ©cimo) + + * More complete coverage in the CI. (#890, #894, #896, Sora Morimoto) + + * Code quality improvement: use exception pattern instead of try-with. (#895, Antonin DΓ©cimo) + + * Code quality improvement: fix warnings on 4.13. (#899) + + +===== 5.4.2 ===== + +====== Bugs fixed ====== + + * Fix compilation on Windows by providing missing dummy stubs (#868, Andreas Hauptmann, Antonin DΓ©cimo). + + +===== 5.4.1 ===== + +====== Bugs fixed ====== + + * Fix Lwt_fmt.stderr to actually point to stderr (#852, #850, Volker Diels-Grabsch). + + * Make temporary files created by Lwt_io.with_temp_dir deletable on Windows by removing the RO bit (#849, #861, Antonin DΓ©cimo). + + * Handle ECONNABORTED in Lwt_io.establish_server* (#829, #830, Reynir BjΓΆrnsson, Hannes Mehnert). + + + +====== Bugfixes ====== + + * Fix Lwt_fmt.stderr to actually point to stderr (#852, #850, Volker Diels-Grabsch). + + * Lwt_io.establish_server* handles ECONNABORTED (#829, #830, Reynir BjΓΆrnsson) + + +===== 5.4.0 (2020-12-16) ===== + +====== Installability ====== + + * Support for OCaml 4.12 (#804, #826, Kate Deplaix). + + * lwt_ppx now uses ppxlib. This introduce a transitive dependency to OCaml.4.04 (#807, Philippe Veber). + +====== Bugfixes ====== + + * Catch exceptions in Lwt_react.of_stream (#809, Petter A. Urkedal). + + * Avoid segfaults in Lwt_unix.tcsetattr (#798, FrΓ©dΓ©ric Fortier). + +====== Additions ====== + + * fork method in Lwt_engine. This method is a noop in the released engines but it paves the way to a libuv-based engine (#811, Ulrik Strid, Anton Bachin). + + * Lwt_main.abandon_yielded_and_paused for use in conjunction with Lwt.fork (#789, Julien Tesson). + + * Lwt.wrap_in_cancelable to complete protect and no_cancel (#785). + + * Support for IOV_MAX in [Lwt_unix.IO_vectors.system_limit (#801, Pino Toscano). + + * Lwt_unix.send_msgto (#805, Antonio Nuno Monteiro). + + * Lwt.dont_wait, a more explicit alternative to Lwt.async (#820, FranΓ§ois ThirΓ©). + +====== Miscellaneous ====== + + * Avoid double-reversing when traversing lists. This may change the order in which some promises are collected, which may change which of several rejection is arbitrarily selected during concurrent traversal (#784). + + * Numerous documentation improvements (including external contributions from Bikal Lem, Sudha Parimala, and Hannes Mehnert). + + + +===== 5.3.0 (2020-04-22) ===== + + * Add let* and and* in Lwt.Syntax and Lwt_result.Syntax (#775, Rahul Kumar). + * Also add let+ and and+ (#776, Craig Ferguson). + * Add Lwt_result.both (#775, Rahul Kumar). + * Always use libev if detected (#601). + +===== 5.2.0 (2020-03-09) ===== + + * Add Lwt_unix.pread, Lwt_unix.pwrite, and Lwt_unix.pwrite_string (#768, + Pierre Chambart). + * Internally use accept4(2) when available (#769, Pierre Chambart). + * PPX: internally use 4.10 ASTs (#765). + +===== 5.1.2 (2020-02-23) ===== + +====== Bugs fixed ====== + + * Do not run C exit hooks after failed exec (#764, diagnosed Lucian Wischik). + * discover.ml: don't add flags for missing system libraries (#760, #761, Olaf + Hering). + * discover.ml: don't run the opam binary (#761). + * Warning on 4.10 in lwt_unix_stubs.c (#766). + +===== 5.1.1 (2020-01-07) ===== + +====== Bugs fixed ====== + + * Exception raised by Lwt_main.run upon call to exit (#758, reported Gal + Schlezinger). + +===== 5.1.0 (2019-12-28) ===== + +====== Additions ====== + + * Lwt.all (9976f67). + +====== Documentation ====== + + * Add index.mld for nicer odoc output (1059a80, prompted Anurag Soni). + * Link to rwo-lwt from the online manual to make it more discoverable + (4129a22, suggested Anurag Soni). + * Fix doc links in opam files (7617607). + +===== 5.0.1 (2019-12-22) ===== + +====== Bugs fixed ====== + + * Additional fix for libev detection under esy (#757, Antonio Nuno Monteiro). + +===== 5.0.0 (2019-12-15) ===== + +====== Breaking ====== + +See #584 for an extended summary and discussion of this release as a whole, or +individual issues for each change specifically. + + * The callback passed to Lwt.async must now evaluate to unit Lwt.t, rather + than _ Lwt.t (#603, requested @cfcs). + * Lwt.choose, Lwt.nchoose, Lwt.nchoose_split, Lwt.pick, and Lwt.npick now + raise Invalid_argument if given the empty list (#557, Tim Reinke). + * Catch nested calls to Lwt_main.run (#607, #609, prompted FranΓ§ois-RenΓ© + Rideau). + * Use the new Lwt_unix.IO_vectors in Lwt_unix.recv_msg and Lwt_unix.send_msg + (#594, prompted Marcello Seri). + * Make Lwt_unix.Async_switch a synonym for Lwt_unix.Async_detach (#572). + * Remove the redundant configure.ml (#700). + * PPX: remove support for general [%lwt ...] expressions (#527). + * PPX: remove support for Lwt_log and the -log option (#520). + * PPX: remove the -no-debug option (#528). + +====== Bugs fixed ====== + + * libev detection under esy (#755, Antonio Nuno Monteiro). + +===== 4.5.0 (2019-12-15) ===== + +====== Additions ====== + + * Implement Lwt_unix.readv and Lwt_unix.writev on Windows using Lwt_unix.read + and Lwt_unix.write (#745, requested Ulrik Strid). + * Implement Lwt_unix.wait4 on Android using Unix.waitpid, as on Windows (#752, + @EduardoRFS). + * LWT_DISCOVER_ARGUMENTS=--verbose flag, passed through environment variable, + for debugging the feature discovery (configuration) process (#740). + +====== Bugs fixed ====== + + * To help with fork, don't call back into Lwt_main at process exit to call Lwt + exit hooks when there are none (#737, prompted Martin Jambon). + * Properly retain references to buffers in Lwt_unix.readv, Lwt_unix.writev, + Lwt_bytes.read, Lwt_bytes.write, and Lwt_bytes.mincore; the references could + be released too early in rare circumstances (#742, prompted Olaf Hering). + * Don't install a SIGCHLD handler when Lwt is linked in but not used (#738, + requested Sam Goldman, additional information Waleed Khan). + * Link with -lpthread on more platforms that support and require the flag + (#748, Olivier Andrieu). + * Fix syntax errors in feature test programs (#748, Olivier Andrieu). + * C warning with OCaml 4.10 (#751, @kit-ty-kate). + +====== Miscellaneous ====== + + * Make tests more reliable (#726, #743, prompted Olaf Hering). + * Fix deprecation annotation on internal API (#735, Antonio Nuno Monteiro). + * Fix broken link in Lwt_mvar docs (#739, reported @tg-x). + * Fix broken links in README (#750, @imbsky). + +===== 4.4.0 (2019-10-09) ===== + +====== Additions ====== + + * ?suffix argument for Lwt_io.with_temp_file and Lwt_io.open_temp_file (#724, + requested Volker Diels-Grabsch). + * Lwt_io.with_temp_dir and Lwt_io.create_temp_dir (#724, requested Volker + Diels-Grabsch). + +====== Changes ====== + + * Lwt_io.establish_server: increase default backlog from 5 to SOMAXCONN (#731, + suggested Konstantin Olkhovskiy). + * PPX: use OCaml 4.09 ASTs to support recent features (074f679). + * PPX: deprecate let%lwt structure items (#733, prompted Didier Le Botlan). + +====== Miscellaneous ====== + + * Tests now pass in more environments (#721, #722, #725, #729, reported Olaf + Hering). + +===== 4.3.1 (2019-09-26) ===== + +====== Bugs fixed ====== + + * Lwt clobbered backtraces (#714, 6e855b8, 4694853, reported Volker + Diels-Grabsch). + * Lwt_unix.fork was broken on glibc 2.28 (#704, @ygrek). + * Fix build with musl-gcc (#718, #719, reported Fabian Hemmer). + * Support more Lwt_unix.madvise options (#716, Anton Kochkov). + +====== Miscellaneous ====== + + * Silence configure script (#717, requested Anil Madhavapeddy). + * Greatly sped up CI and tests. + +===== 4.3.0 (2019-08-20) ===== + +====== Planned to break in 5.0.0 ====== + + For general discussion of breakage in Lwt 5.0.0, see #584. See #293 about how + Lwt announces and does breaking changes.* + + * The signature of Lwt.async will change from (unit -> 'a Lwt.t) -> unit to + (unit -> unit Lwt.t) -> unit (#603, prompted @cfcs). + * Lwt_unix.send_msg and Lwt_unix.recv_msg will be changed to take + Lwt_unix.IO_vectors.t instead of Lwt_unix.io_vectors (#702, prompted + Marcello Seri). + * Nesting calls to Lwt_main.run will be forbidden, and will raise an + Failure. Most programs don't do this (#609, prompted FranΓ§ois-RenΓ© Rideau). + * configure.ml will be removed in favor of an improved discover.ml This + affects only users who are configuring Lwt as part of a manual installation + (i.e., not users of opam or esy). See discover.ml for usage (#700). + * Lwt_unix.async_method will have no effect. In practice, it already does + nothing, and has almost no users (#572). + +====== Additions ====== + + * Lwt_process: allow setting working directory for new processes (#694, Thomas + Leonard). + * PPX: use OCaml 4.08 ASTs to support latest features (#697). + * Lwt_io.NumberIO: use compiler intrinsics for better performance (#178, + requested Mauricio Fernandez). + +====== Bugs fixed ====== + + * Race condition in Lwt_react.S.limit (4e592eb). + * Use fallback rule during configuration (#693, Hongchang Wu). + * Fix typos (#688, #692, @Fourchaux). + +===== 4.2.1 (2019-04-02) ===== + +====== Bug fixed ====== + + * Detect libev correctly when building under esy (#679, Antonio Nuno + Monteiro). + +===== 4.2.0 (2019-03-25) ===== + +====== Additions ====== + + * Lwt.both (#668, Brendan Long, Jeremy Yallop). + * ppx_let support with open Lwt.Infix (#667, Brendan Long). + * Lwt_stream.of_seq (#646, Hezekiah Carty). + * Lwt_io.is_closed (#635, Andreas Garnaes). + * Lwt_unix.IO_vectors.byte_count (#645, RaphaΓ«l Proust). + * Support for higher baud rates in Lwt_unix.tcgetattr and Lwt_unix.tcsetattr + (#678, FrΓ©dΓ©ric Fortier). + * Replacement functions in Lwt_main for deprecated functions based on + Lwt_sequence (#660). + +====== Bugs fixed ====== + + * 4.08 compatibility (#658). + * Stack overflow in Lwt_stream.iter_p (#432, Varun Kohli). + * Incorrect bounds check in Lwt_bytes.mincore (#627, CΓ©dric Le Moigne). + * Lwt_bytes.mincore will not be available in future releases of OpenBSD (#663, + Kenneth Westerback). + * Missing header in the Android build (#652, Justus Matthiesen). + * Build broken on MSVC (98303de, 85535f7, Dmitry Bely). + * Build broken on OpenBSD (#672, Christopher Zimmermann). + * Lwt_io.of_bytes produces a channel with inaccurate positions (#636, Nathan + Rebours). + * Lwt_io._.read_int behaves incorrectly on 32-bit systems (#671, reported + Dmitry Bely). + * Inaccurate locations for errors related to ;%lwt (#602, @kandu). + * (_ : t) not recognized as a catch-all pattern by the PPX (#640, Florian + Angeletti). + * Race condition in Lwt_react.E.limit (#606, Avni Fatehpuria). + * Premature deallocation in Lwt_react.E.with_finaliser and + Lwt_react.S.with_finaliser (#626, El-Hassan Wanas). + +====== Miscellaneous ====== + + * New tests for Lwt_bytes, portions of Lwt_unix (#619, #621, #628, #630, #673, + CΓ©dric Le Moigne, Anurag Soni). + * Test suite improvements (#656, Dave Parfitt). + * Clarifications for documentation of Lwt.try_bind, Lwt.pick (#648, #650, + Bikal Lem). + * Fixed documentation of Lwt_io.read_line (#657, Yoni Levy). + * Fixed some typos (#611, #613, Rich Neswold). + +===== 4.1.0 (2018-06-26) ===== + +====== Additions ====== + + * Change license to MIT (#560). + * Lwt_fmt, an Lwt-aware version of Format (#548, Gabriel Radanne). + * Lwt_io.establish_server_with_client_socket (#586). + +====== Bugs fixed ====== + + * Lwt_stream.iter_n: rename ?max_threads argument to ?max_concurrency (#581, + Hezekiah Carty). + * PPX: reject match expressions that have only exception cases (#597, RaphaΓ«l + Proust). + +====== Miscellaneous ====== + + * Improvements to Lwt_pool docs (#575, Bobby Priambodo). + * Restore all PPX tests (#590, Jess Smith). + +===== 4.0.1 (2018-04-13) ===== + +====== Bugs fixed ====== + + * Race condition in worker thread management in Lwt_unix (#569, diagnosed Gabe + Levi). + * Hang in Lwt_unix.read on Windows (#574, #569, 86a6baf, diagnosed Gabe Levi). + * Docs: note that Lwt_io.open_file for writing truncates the file by default + (#570, reported TΓ³th RΓ³bert). + +===== 4.0.0 (2018-03-30) ===== + +====== Breaking ====== + +These changes were announced in Lwt 3.1.0 and Lwt 3.2.0. See #453 about smooth +upgrade paths. + + * Delete package lwt.ppx. The PPX syntax is in package lwt_ppx since Lwt 3.2.0 + (#338). + * Remove >> syntax from the PPX (#495). + * Delete modules Lwt_log, Lwt_daemon, Lwt_log_core, and package lwt.log. These + are in package lwt_log since Lwt 3.2.0, but it is recommended to use + Logs_lwt from the logs library instead (#484, initiated Hannes Mehnert). + * Delete package lwt.preemptive. It is an alias for lwt.unix since Lwt 3.2.0 + (#487). + * Delete package lwt.syntax. The Camlp4 syntax is in package lwt_camlp4 since + Lwt 3.2.0 (#370). + * Delete module Lwt_chan, a predecessor of Lwt_io (#441). + * Delete package lwt.simple-top, a predecessor of utop (#371). + * Make resolvers (Lwt.u) contravariant (#458). + +====== Planned to break in 5.0.0 ====== + + * Lwt.pick will raise Invalid_argument on the empty list, instead of returning + a forever-pending promise. Also applies to Lwt.choose, Lwt.npick, + Lwt.nchoose, and Lwt.nchoose_split (#562, Tim Reinke, prompted Hezekiah + Carty). + * Remove translation of [%lwt ...] to Lwt.catch from the PPX (#527). + * Remove -no-debug option from the PPX (#528). + * Remove Lwt_log support from the PPX (#520). + +====== Bugs fixed ====== + + * Lwt_io.file_length now fails with EISDIR when used on a directory (#563, + requested Cedric Cellier). + * Lwt_react.E.limit and Lwt_react.S.limit now working more correctly (#566, + @Freyr666). + +====== Miscellaneous ====== + + * Documentation improvements (#561, Jason Evans). + +===== 3.3.0 (2018-03-07) ===== + +====== Bugs fixed ====== + + * Restore backtrace support (#554, #556, Gabe Levi). + * Serious logic error that could cause Lwt to hang or crash (#549, reported + @koen-struyve). + * All Lwt_list functions are now tail-recursive (#538, Joseph Thomas). + +====== Additions ====== + + * Support ;%lwt syntax in the PPX (#307, Hezekiah Carty). + * Lwt_stream.iter_n (#312, Hezekiah Carty). + +====== Miscellaneous ====== + + * Testing improvements (#536, #541, @cedlemo). + * Documentation improvements (#544, #546, #547, #553, #559, Daniil Baturin, + Jason Evans, Jess Smith, Milo Turner). + +===== 3.2.1 (2018-01-11) ===== + +Lwt 3.2.1 is released because it still packages lwt.ppx, a deprecated copy of +package lwt_ppx, and the two packages should be kept in sync. + +====== Deprecations ====== + + * All PPX options are deprecated and should not be used (#534). + * The [%lwt ...] PPX syntax should be replaced by Lwt.catch (#534). + +====== Fixes ====== + + * Clean up PPX -help usage message output (#525, Zan Doye). + +====== Miscellaneous ====== + + * More thorough testing (#512, #535, Joseph Thomas). + * Clarification of the C binding (#521, @cedlemo). + +===== 3.2.0 (2017-12-19) ===== + +====== Additions ====== + + * Lwt_mvar.take_available, Lwt_mvar.is_empty (#459, Hezekiah Carty). + * Lwt_io.open_temp_file, Lwt_io.with_temp_file (#467, Joe Thomas). + * New reference documentation for module Lwt (#469). + * Lwt_pool.clear and ?dispose argument for Lwt_pool.create (#483, + Hezekiah Carty). + * Lwt_pool.wait_queue_length (#493, Jerome Vouillon). + +====== Bugs fixed ====== + + * Lwt.npick never worked (#447, Zack Coker). + * Lwt_pool.use now always calls ?validate on elements (#461, Joe Thomas). + * Better locations generated by the PPX (#470, Fabian Hemmer). + * Keep worker thread count accurate in Lwt_unix when pthread_create fails + (#493, @koen-struyve). + * Leaked exceptions in Lwt_list (#499). + * Memory leak in Lwt_unix.getnameinfo (#503, Hannes Mehnert). + +====== Planned to break in 4.0.0 ====== + +See #453 for details and instructions about planned breakage in Lwt 4.0.0. + + * The semantics of Lwt will be adjusted for better exception and stack safety + (#500). + * The PPX will be factored out into its own opam package, lwt_ppx. This + package is installable from opam now, as of Lwt 3.2.0 (#338). + * Similarly, the deprecated Camlp4 syntax will be factored out into + lwt_camlp4, which is installable from opam now (#370). + * Modules Lwt_log, Lwt_log_core, Lwt_log_rules, and Lwt_daemon are being + deprecated and factored out into opam package lwt_log, also installable from + opam now. Use the logs library for logging, in particular module Logs_lwt. + Direct daemonization is deprecated on most platforms (#484, Hannes Mehnert). + * The >> construct from the PPX will be deleted (#471, RaphaΓ«l Proust). + * Package lwt.preemptive is being merged into lwt.unix. In 3.2.0, + lwt.preemptive becomes an alias for lwt.unix, and the package name + lwt.preemptive will be deleted in 4.0.0 (#487). + +====== Deprecations ====== + + * Lwt.waiter_of_wakener should not be used, as it can lead to soundness bugs + in future (but not current) Lwt (#458). + * Lwt_sequence was deprecated in Lwt 2.6.0, but it now has a warning attached, + as do Lwt.add_task_r and Lwt.add_task_l, which use it (#361). + * Use of the following functions is discouraged, but they have not yet + received deprecation warnings: Lwt.with_value, Lwt.cancel, Lwt.state, + Lwt.ignore_result (#359, #469). + +====== Miscellaneous ====== + + * Replace references to Camlp4 in the manual with the PPX (#457, Bobby + Priambodo). + * More tests for Lwt_pool (#464, Joe Thomas). + * Expect tests for the PPX (#474, Fabian Hemmer). + +===== 3.1.0 (2017-07-19) ===== + +====== Additions ====== + + * Port to Jbuilder (#374, Andrew Ray). + * Lwt_io.establish_server_with_client_address (#346, Rudi Grinberg). + * Lwt_unix.getcwd (#403, RaphaΓ«l Proust). + +====== Planned to break in 4.0.0 ====== + + * Delete lwt.simple-top (#371). + * Delete Lwt_chan (#441). + +====== Fixes ====== + + * Make Lwt_log functions tail-recursive (#348, Jan Doms). + * Make more of Lwt_list tail-recursive (#347, Jan Doms). + * Improve string messages in exceptions (#368, #382, Jan Doms, RaphaΓ«l + Proust). + * Don't call Unix.set_nonblock or Unix.clear_nonblock unnecessarily on + some fds (#356, David Sheets). + * Lwt_unix.sleep and Lwt_unix.timeout returning too early when using + libev (#433, Stijn Devriendt). + * Lwt_sequence.fold_r iterating the wrong way in some cases (#405, + Stijn Devriendt). + * Build conflicts in some cases due to duplicate cst_to_constr + function (#362, JΓ©rΓ©mie Dimino). + * Don't use deprecated readdir_r system call (#430, RaphaΓ«l Proust). + +====== Miscellaneous ====== + + * The Lwt core, lwt.ml, has been thoroughly refactored and commented + (#354, reviewed Gabriel Radanne, Edwin TΓΆrΓΆk, RaphaΓ«l Proust, Jan + Doms, Fabian Hemmer, Sebastien Mondet, Simon Cruanes, Anil + Madhavapeddy, Pierre Chambart, and many others). + * Lots of tests for most of the Lwt core (#339, #389, #392, #440, + #448, #450, Joseph Thomas, Ryan Slade). + * Documentation fixes (including by Joseph Thomas, RaphaΓ«l Proust, + Richard Degenne, Stavros Polymenis). + * Contributing documentation (#379). + * Massively adjust whitespace for legibility (#400, #409, #416, + Richard Degenne). + * Improvements to CI (Etienne Millon, Raphael Rafatpanah, Zack Coker, + Yotam Barnoy). + * The additional packages lwt_ssl, lwt_react, lwt_glib get new minor + releases, the change being new Jbuilder build systems (#374, Andrew + Ray). + +===== 3.0.0 (2017-04-10) ===== + +====== Breaking ====== + + * These changes were originally announced in release 2.7.0 (#308). + * Lwt_engine.libev now has an optional argument for selecting the libev back + end (#269, #294, Jeremy Yallop). + * Lwt_io.establish_server has been changed to make it more difficult to leak + file descriptors (#258, #260). + * Lwt_io.shutdown_server now evaluates to a promise, which completes when the + listening socket's close(2) operation completes (#259). + * Lwt_unix.bind now evaluates to a promise, because the bind(2) system call + can block for Unix domain sockets (#296, requested David Sheets). + * ocamlfind packages lwt.react, lwt.ssl, lwt.glib are replaced by lwt_react, + lwt_ssl, lwt_glib. These have been separate OPAM packages, under those + names, since 2.7.0 (#301). + +===== 2.7.1 (2017-04-08) ===== + +====== Fixes ====== + + * OCaml 4.05 compatibility (Mauricio Fernandez, #322). + * Give Lwt_unix.file_exists the same semantics as Sys.file_exists, with + respect to not raising Unix.Unix_error (Mauricio Fernandez, #316). + * Improve diagnostics from build scripts (Tim Cuthbertson, #313, #314). + +====== Additions ====== + + * Announce Lwt_result, which was originally released as an experimental module + in release 2.6.0 (Simon Cruanes, #320, #247). + +===== 2.7.0 (2017-01-03) ===== + +====== General ====== + + * Values of types a Lwt.t are now referred to as promises rather than threads + (#300). The manual has not yet been updated. + +====== Breaking ====== + + * After this release, Lwt will switch to semantic versioning. Future breaking + changes will first require deprecation, then a major version number increase + (#293). + * Lwt no longer supports OCaml 4.01 (#272). + * Lwt_unix.fdatasync is no longer available on macOS. It was calling an + undocumented system call on that system (#285, Jeremy Yallop). + +====== Planned to break in 3.0.0 ====== + + * APIs in this category have deprecation messages attached. The messages will + be displayed if you recompile your code, and can also be seen in #308. + * Lwt_engine.libev will have an argument for selecting the libev back end + (#269, #294, Jeremy Yallop). + * Lwt_io.establish_server will be replaced by a version that makes it + difficult to leak file descriptors (#258, #260). + * Lwt_io.shutdown_server will evaluate to a promise, which indicates when the + close operation completes (#259). + * Lwt_unix.bind will evaluate to a promise, since bind can block for Unix + domain sockets (#296, requested David Sheets). + * ocamlfind packages lwt.react, lwt.ssl, and lwt.glib will be replaced by the + new lwt_react, lwt_ssl, and lwt_glib. These are now distributed in new OPAM + packages with the same names, separately from OPAM package lwt (#301). + +====== Additions ====== + + * Lwt_unix.readv and Lwt_unix.writev - zero-copy scatter/gather I/O + (#291, #299). + * ?fail_on_error argument for Lwt_log.load_rules (#306, Daniil Baturin). + * Lwt_log.level_of_string (#306, Daniil Baturin). + +====== Changes ====== + + * Lwt_stream.of_list, Lwt_stream.of_array, Lwt_stream.of_string now + immediately push all elements into the created streams + (#239, Spiros Eliopoulos). + +====== Deprecations ====== + + * Lwt_stream.map_exn in favor of Lwt_stream.wrap_exn, which uses OCaml's + standard result type (#295). + +====== Bugs fixed ====== + + * Ungraceful failure if directory handle used after Lwt_unix.closedir (#292). + * Buffer overflow in Lwt_unix.readdir and Lwt_unix.readdir_n (#292). + * Unnecessary allocations in Lwt_unix.readdir_n (#292, found Jeremly Yallop). + +====== Miscellaneous ====== + + * Annotate existing deprecations with [@@ocaml.deprecated ...] (5737f5b). + * Improvements to the examples (#288, Rich Neswold). + * Documentation fixes, including by Rich Neswold. + * New tests and various minor internal improvements. + * Run tests in CI with all OCaml warnings enabled (dadb926). + * Much cleaner build output. + * Add scratch/ directory for local use by developers. + +===== 2.6.0 (2016-10-27) ===== + +====== Additions ====== + + * Lwt_stream.closed and Lwt_stream.is_closed (#223, Spiros Eliopoulos). + * Lwt_switch.with_switch (#256, Thomas Leonard). + * Define 'a Lwt.result as ('a, exn) result (#247, Simon Cruanes). + * Lwt_condition.broadcast_exn (#241, Nicolas Ojeda Bar). + * Lwt_unix.utimes (#193). + +====== Bugfixes ====== + + * Memory leak in Lwt_unix.readdir_n (#229, diagnosed Thomas Leonard). + * Memory leak in Lwt.protected (#56, #181, reported @ygrek, Mauricio + Fernandez). + * Lwt_switch.turn_off hook exception handling (995b704). + * Handling of ENOTCONN when channels passed to handler of + Lwt_io.establish_server are closed (95fb431). + * Duplicate exceptions on implicit close in Lwt_io.with_connection (b1afe45). + * Deadlock in Lwt_main.at_exit (#48, #114, reported JΓ©rΓ΄me Vouillon, Vincent + Bernardoff). + * Performance of Lwt_preemptive.detach (#218, #219, Mauricio Fernandez). + * Bad hash functions for libev loops (#146, reported Mark Christiaens). + * Hash of uninitialized data in Lwt_io (#217, reported Jeremy Yallop). + * Update log sections after Lwt_log.load_rules (#188, reported @rand00). + * Print three digits for milliseconds in Lwt_log (#264, Fabian Hemmer). + * Do not truncate Unix job notification ids in C (#277, diagnosed + @stijn-devriendt). + +====== Deprecations ====== + + * Lwt_stream.on_termination: bind on Lwt_stream.closed instead. + * Lwt.make_value, Lwt.make_error: use result's Ok and Error constructors. + * Lwt_pqueue, Lwt_sequence: use min-heaps and linked lists from another + library (#135). + * Pa_lwt, Pa_lwt_log: use Ppx_lwt. + +====== Miscellaneous ====== + + * Update examples to use PPX syntax instead of Camlp4 (#108, Peter Zotov). + * Set up Travis, AppVeyor for testing on Linux, OS X, Cygwin, and MinGW. MSVC + also planned. + * Large amount of local documentation fixes (Hezekiah Carty, Etienne Millon, + Leo Wzukw, Sebastien Mondet, reports by others). + * A bunch of new tests. + +===== 2.5.2 (2016-04-25) ===== + + * Fix compatibility for 4.03 (#227) + * Various documentation fixes (#199,#200,#210) + * Improve wildcard detection in the ppx (#198) + * Fix Lwt_stream: bounded_push#close wake the reader (#201) + * Fix infinite loop with Lwt_stream.choose (#214) + * Fix laziness failure with Lwt_io.common#close (#207) + +===== 2.5.1 (2015-12-07) ===== + + * Lwt_stream.on_terminate -> Lwt_stream.on_termination + * Lwt_unix: handle O_CLOEXEC + * Lwt_log: add OSX syslog path + * Ppx: Improve lwt%match, improve catchall detection + * Add Lwt_unix.file_exists and Lwt_unix.Large_file.file_exists + * Build fixes + +===== 2.5.0 (2015-07-03) ===== + + * API CHANGE: Functions in Lwt_io that were previously using a + ~buffer_size argument now takes a ~buffer argument. + * Accept ?buffer argument in Lwt_ssl.{in,out}_channel_of_descr. + * Use newer Ssl bigarray read/write functionality to avoid + allocation in Lwt_ssl. + * Fix non-reentrant function calls (#136) + * IPv4 multicast support. + * Add support for if%lwt in ppx extension. + * Add Lwt.return_some. + * Disable log syntax extension by default in ppx. + Give [-log] as ppx argument to enable it. + * Nanosecond precision for Lwt_unix.stat. + * Minor fixes + documentation improvements. + +===== 2.4.8 (2015-03-11) ===== + + * Fix compilation under Windows (#117, #129) + * Fix Lwt_engine.on_timer (#121) + * Add Lwt_log_core.reset_rules (#123) + * Fixed typos in the documentation (#119, #131) + +===== 2.4.7 (2015-01-06) ===== + + * camlp4 is now optional. + * Add safe_string compliance except for Lwt_ssl (need ocaml-ssl fix). + * Add Lwt.Infix module to open instead of Lwt to have (>>=), etc. + * Add Lwt_list.filter_map_{s,p} functions. + * Add Lwt.fail_{with,invalid_arg} functions. + * Improved Android support. + * Remove deprecated lwt.text and lwt.top libraries. + * Remove deprecated Lwt_signal and Lwt_event modules from + lwt.react. + * Fix #111: try_lwt wrongly warns about unused match case. + * Fix #96: Fix Lwt_react.S.limit and Lwt_react.E.limit. + * Fix #91: Workaround to fix compilation on OSX. + +===== 2.4.6 (2014-10-12) ===== + + * Add a ppx syntax extension + * Add a ?fd argument to + Lwt_io.{open_connection,with_connection,establish_server}. + * Fix stub for getaddrinfo and getprotobyname + * Windows fix: don't throw an exception in the notification handler + if we're shutting down + * Fix include file search in ./configure + * ./configure fixes for windows + * Fix: use sys_exit instead of exit when Unix.execv fails + +===== 2.4.5 (2014-04-21) ===== + + * Lwt_ssl: expand API to allow setting socket options with Ssl + functions + * fix for camlp4 trunk + * support for React 1.0.0 + * add Lwt_sequence.find_node_* functions + * Lwt_log: get backtrace early to overcome exns in + Printexc.to_string + * fix potential deadlock in lwt_unix_recv_notifications + * lwt.glib fixes: + - handle HUP + - fix for BSD/OSX + * do not raise an exception in Lwt_log if argv[0] is blank + +===== 2.4.4 (2013-10-22) ===== + + * add Android support + * fix issues in stubs for Lwt_unix jobs + * fix compatibility issue with OCaml 4.01 + * fix the stub for ev_timer_init + * add Lwt.log containing Lwt_log_core, the Unix-free part of Lwt_log + * add Lwt_ssl.get_fd + * fix stdout/stderr redirections in Lwt_daemon.daemonize + * add Lwt_list.{map,iter}i{_s,_p} + +===== 2.4.3 (2012-12-27) ===== + + * fix Lwt_ssl.{in,out}_channel_of_descr: shutdown and close the + socket when the channel is closed + +===== 2.4.2 (2012-09-28) ===== + + * fix the stub for Lwt_unix.readdir + * change the default method for Lwt_glib.install + (use the glib main loop by default: more portable) + * ignore invalid file descriptors returned by glib + (like the emulation of select in glib does) + * use environment variables in discover.ml + - use LIBRARY_PATH and C_INCLUDE_PATH for searching headers + - allow to pass flags for a library in _CLFAGS and _LIBS + * add Lwt_unix.on_signal_full + +===== 2.4.1 (2012-08-22) ===== + + * Add Lwt_stream.on_terminate + * Fix Lwt_gc + * Fix stubs for get_credentials on *BSD + +===== 2.4.0 (2012-07-16) ===== + + * Reimplement Lwt_stream + - much simpler and more efficient + - do not use Weak + - add bounded push streams + * Add Lwt.async + * Add Lwt_preemptive.run_in_main + * Implement Lwt_unix.get_credentials on MacOS X/OpenBSD + * Ensure that on_cancel functions are executed first + * Better implementation of Lwt.cancel with more tests + * Simplify the API for unix jobs + * Better handling of the master lock in libev stubs + * Windows fixes/updates: + - pass -lws2_32 instead of ws2_32.lib if building with mingw + - fix a bug causing Lwt_unix.read/write to block when a socket + is not readable/writable + - port Lwt_process and Lwt_unix.system to Windows + * Compatibility with OCaml 4.00: + - add O_SHARE_DELETE to Lwt_unix.open_flag + - add -package compiler-libs.toplevel for files using Toploop + * Do not use module Sys for signal handling to avoid + OCaml code to be called in a C thread + * Fix Lwt_unix.wrap_syscall: try instead of Lwt.catch + * Fix a dead-lock between lwt_unix_send_notification + and lwt_unix_recv_notifications + * Fix #277: add a function to return the Ssl.socket of a Lwt_ssl.socket + * Fix problems with C libraries detection/linking + +===== 2.3.2 (2011-11-04) ===== + + * Add location informations in logs: + ** allow loggers to get the current location through local storage + ** pass current location to logging functions + ** pass the current location with the syntax extension + * Add Lwt.on_termination + * Add Lwt_unix.reinstall_signal_handler + * Add Lwt_io.flush_all + * Add assert_lwt keyword to the syntax extension + * Add Lwt.wrap + * Add Lwt_glib.iter and Lwt_glib.wakeup + * OCaml 3.13 ready + * Allow to compile without libev support + * Fix bugs in Lwt_io + * Better handling of forks + * Fix many problems on Windows + +===== 2.3.1 (2011-07-13) ===== + + * Fix building of documentation when using the tarball + * Add Lwt_unix.fsync and Lwt_unix.fdatasync + * Fix the stubs for Lwt_unix.send_msg when fd-passing is not + available + * Add -lwt-sequence-strict option to the syntax extension + * Use a custom PRNG state for Lwt.choose and Lwt.pick + * Fix a display glitch when starting the toplevel + * Add Lwt_unix.fork which should now be used when one want to use + Lwt in the child process + * Better implementation of Lwt_unix.readlink and + Lwt_unix.gethostbyname, which fixes compilation on Hurd + * Add Lwt.wakeup_later and Lwt.wakeup_later_exn to be used when one + need to do lot of nested wakeup, which fixes a buffer overflow in + Lwt_mutex + * Fix Lwt_unix.abort and Lwt_unix.close (threads was never wakeup) + * Fix Lwt_throttle for correct timings + * Fix subtle use of cancel + +===== 2.3.0 (2011-04-12) ===== + + * Add an extensible system of engines to: + ** allow the user to replace libev by another event system, such + as select + ** allow easier integration of external libraries supporting + asynchronous operations + * Lots of improvements for Windows: + ** use the OCaml select instead of libev by default on Windows + ** make asynchronous operations on non-socket file descriptors + such as pipes to work + ** make glib integration to work + * Better use of engines in Lwt_unix: now events are cached to minimize + the amount of calls to epoll_ctl + * Use an eventfd when possible for notifications for faster delivery + * Add modules: + ** Lwt_sys: allow to test availability of extra features + ** Lwt_react: replace Lwt_event and Lwt_signal + * Allow to configure logging rules at runtime in Lwt_log + * Add match_lwt and while_lwt to the syntax extension + * Fixes: + ** syntax extension: handle "lwt ... = ... in ..." at toplevel + ** make the notification system fork-proof + ** fix an issue with stubs not raising correctly exceptions + +===== 2.2.1 (2011-01-26) ===== + + * Better interaction with Js_of_OCaml. + * Add functions {{{Lwt.register_pause_notifier}}} and {{{Lwt.paused_count}}}. + +===== 2.2.0 (2010-12-13) ===== + + * Bugfixes: + ** Fix a bug with cancellable threads causing {{{Canceled}}} + exceptions to be raised randomly + ** Fix a fd-leak in Lwt_io.open_connection + * {{{Lwt_unix}}} now use libev instead of select + * Add thread local storage support to {{{Lwt}}} + * Add backtrace support to {{{Lwt}}}. Now {{{Lwt}}} exceptions can + be recorded by using the syntax extension with the {{{-lwt-debug}}} + command line switch. + * Allow blocking system calls to be executed in parallels + * Change the type of many functions of {{{Lwt_unix}}}, which now + return a {{{Lwt}}} thread + * Add functions {{{Lwt_unix.readable}}} and {{{Lwt_unix.writable}}} + * Add function {{{Lwt_io.is_busy}}} + * Add functions {{{Lwt_event.delay}}} and {{{Lwt_signal.delay}}} + * Add function {{{Lwt_term.render_update}}} + * Add function {{{Lwt_ssl.embed_socket}}} + * Add module {{{Lwt_bytes}}} defining operations on bigarrays + instead of strings + * Use bigarrays in Lwt_io instead of strings for the internal buffer. + Lwt_io.make now takes a function that uses a bigarray. + * Add module {{{Lwt_switch}}} + +===== 2.1.1 (2010-06-13) ===== + + * Many bugfixes, including: + ** buggy behaviour of cancellable threads + ** file descriptor leakage in {{{Lwt_unix.accept_n}}} + * Add {{{Lwt.nchoose}}} and {{{Lwt.npick}}} + * Use {{{set_close_on_exec}}} for fds created by {{{Lwt_log}}} + * Better implementation of lwtized react functions + +===== 2.1.0 (2010-04-19) ===== + + * Rename {{{Lwt.select}}} to {{{Lwt.pick}}} + * Removing module {{{Lwt_monitor}}} in favour of {{{Lwt_mutex}}} and + new module {{{Lwt_condition}}} + * More react helpers: + ** {{{Lwt_event.next}}} + ** {{{Lwt_event.limit}}} and {{{Lwt_signal.limit}}} + ** {{{Lwt_event.from}}} + * Adding function {{{Lwt_main.fast_yield}}} + * Adding unit tests + * Optimisation of {{{Lwt}}} + * Adding module {{{Lwt_log}}} for logging + * Adding a camlp4 filter for remmoving logging statement or inlining + tests + * Adding module {{{Lwt_daemon}}} + * Adding function {{{Lwt_unix.recv_msg}}} and {{{Lwt_unix.send_msg}}} + * Adding function {{{Lwt_unix.wait4}}} + * Adding function {{{Lwt_io.establish_server}}} + * Adding module {{{Lwt_list}}} + * Enhancement in {{{Lwt_process}}}, it now support redirections and + timeouts + * Allow to use {{{select}}} on arbitrary high file descriptors + * More commands and features in {{{Lwt_read_line}}}: + ** Handle "undo" command + ** New controllable read-lines instances + ** More edition commands + ** Completion as you type + ** Backward search + * Enhancement in {{{Lwt_term}}}: more drawing functions and allow to + put the terminal into drawing mode + * Optimisation of {{{Lwt_stream}}} + * Optimisation of {{{Lwt_io.write_char}}} and {{{Lwt_io.read_char}}} + * Bugfix of {{{Lwt_stream}}}: two parallel {{{Lwt_stream.get}}} + returned the same value + * Bugfix in {{{Lwt_unix.connect}}}: it returned immediately on EINPROGRESS + * Bugfixes in {{{Lwt_glib}}}: file descriptors were not monitored correctly + +===== 2.0.0 (2009-10-15) ===== + + * Adding modules: + ** {{{Lwt_stream}}}: lwt-aware version of the {{{Stream}}} module + ** {{{Lwt_gc}}} for using {{{finalise}}} without + {{{Lwt_unix.run}}} + ** {{{Lwt_io}}}: a new implementation of buffered channels with + more features and better handling of concurrent access + ** {{{Lwt_text}}}: implementation of text channels + ** {{{Lwt_process}}}: helpers to spawn processes and communicate + with them + ** {{{Lwt_main}}} for abstracting the main loop and allowing + replacement by a custom main loop + ** {{{Lwt_glib}}} for integration into the glib main event loop + ** {{{Lwt_term}}} for interaction with the terminal + ** {{{Lwt_read_line}}} for interactive user input + ** {{{Lwt_monitor}}}, {{{Lwt_mvar}}}: combined locks for + synchronization with conditional variables for notification + ** {{{Lwt_throttle}}} for limiting rate of execution + (e.g. for authentication procedure) + ** {{{Lwt_sequence}}}: mutable sequence of elements + ** {{{Lwt_event}}}, {{{Lwt_signal}}}: helpers for reactive + programming with lwt + * Adding a syntax extension {{{pa_lwt}}}: + ** handles anonymous bind {{{a >> b}}} + ** adds syntactic sugar for catching errors (ticket #6) + ** adds syntactic sugar for parallel let-binding construction + ** adds syntactic sugar for for-like loops + * Top-level integration: + ** threads can runs while reading user input + ** line editing support + * New enhanced OCaml toplevel with some basic completion features + * Adding C stubs to reimplement {{{Unix.read}}} and {{{Unix.write}}} + with assumption of non-blocking behaviour + * Adding more functions/helpers in {{{Lwt}}} + * Fixing memory leaks in {{{Lwt.choose}}} + * Bugfix in {{{Lwt_chan.close_*}}} (ticket #66) + * Separate the type of threads (covariant) from the type of thread + wakeners (contravariant); the type of many functions related to + {{{Lwt.wait}}} has been changed + * Add cancelable threads + * Unix-dependent part is now put in its own archive and findlib + package. + +===== 1.1.0 (2008-06-25) ===== + + * Adding module {{{Lwt_pool}}} for creating pools (for example pools + of connections) + * Adding a few functions in {{{Lwt_chan}}} + * Fixing bugs in {{{Lwt_util.map_serial}}} and + {{{Lwt_util.iter_serial}}} + * Putting {{{Lwt_preemptive}}}, {{{Lwt_lib}}} and {{{Lwt_ssl}}} in + separate libraries and findlib subpackages so that lwt.cma depends + only on unix.cma. + +===== 1.0.0 (and before) ===== + + * See Ocsigen changelog diff --git a/dev/lwt/_doc-dir/LICENSE.md b/dev/lwt/_doc-dir/LICENSE.md new file mode 100644 index 00000000..0c2afacb --- /dev/null +++ b/dev/lwt/_doc-dir/LICENSE.md @@ -0,0 +1,19 @@ +Copyright (c) 1999-2020, the Authors of Lwt (docs/AUTHORS) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dev/lwt/_doc-dir/README.md b/dev/lwt/_doc-dir/README.md new file mode 100644 index 00000000..1c94c14d --- /dev/null +++ b/dev/lwt/_doc-dir/README.md @@ -0,0 +1,187 @@ +# Lwt + +[![version][version]][releases] [![GitHub Actions status][github-actions-img]][github-actions] + +[version]: https://img.shields.io/github/release/ocsigen/lwt +[releases]: https://github.com/ocsigen/lwt/releases +[github-actions]: https://github.com/ocsigen/lwt/actions +[github-actions-img]: https://github.com/ocsigen/lwt/actions/workflows/workflow.yml/badge.svg?branch=master +[appveyor]: https://ci.appveyor.com/project/aantron/lwt/branch/master +[appveyor-img]: https://img.shields.io/appveyor/ci/aantron/lwt/master.svg?label=appveyor + +Lwt is a concurrent programming library for OCaml. It provides a single data +type: the *promise*, which is a value that will become determined in the future. +Creating a promise spawns a computation. When that computation is I/O, Lwt runs +it in parallel with your OCaml code. + +OCaml code, including creating and waiting on promises, is run in a single +thread by default, so you don't have to worry about locking or preemption. You +can detach code to be run in separate threads on an opt-in basis. + +Here is a simplistic Lwt program which requests the Google front page, and fails +if the request is not completed in five seconds: + +```ocaml +open Lwt.Syntax + +let () = + let request = + let* addresses = Lwt_unix.getaddrinfo "google.com" "80" [] in + let google = Lwt_unix.((List.hd addresses).ai_addr) in + + Lwt_io.(with_connection google (fun (incoming, outgoing) -> + let* () = write outgoing "GET / HTTP/1.1\r\n" in + let* () = write outgoing "Connection: close\r\n\r\n" in + let* response = read incoming in + Lwt.return (Some response))) + in + + let timeout = + let* () = Lwt_unix.sleep 5. in + Lwt.return None + in + + match Lwt_main.run (Lwt.pick [request; timeout]) with + | Some response -> print_string response + | None -> prerr_endline "Request timed out"; exit 1 + +(* ocamlfind opt -package lwt.unix -linkpkg example.ml && ./a.out *) +``` + +In the program, functions such as `Lwt_io.write` create promises. The +`let* ... in` construct is used to wait for a promise to become determined; the +code after `in` is scheduled to run in a "callback." `Lwt.pick` races promises +against each other, and behaves as the first one to complete. `Lwt_main.run` +forces the whole promise-computation network to be executed. All the visible +OCaml code is run in a single thread, but Lwt internally uses a combination of +worker threads and non-blocking file descriptors to resolve in parallel the +promises that do I/O. + + +
+ +### Overview + +Lwt compiles to native code on Linux, macOS, Windows, and other systems. It's +also routinely compiled to JavaScript for the front end and Node by js_of_ocaml. + +In Lwt, + +- The [core library `Lwt`][core] provides promises... +- ...and a few pure-OCaml helpers, such as promise-friendly [mutexes][mutex], + [condition variables][cond], and [mvars][mvar]. +- There is a big Unix binding, [`Lwt_unix`][unix] that binds almost every Unix + system call. A higher-level module [`Lwt_io`][io] provides nice I/O channels. +- [`Lwt_process`][process] is for subprocess handling. +- [`Lwt_preemptive`][preemptive] spawns system threads. +- The [PPX syntax][ppx] allows using all of the above without going crazy! +- There are also some other helpers, such as [`Lwt_react`][react] for reactive + programming. See the table of contents on the linked manual pages! + +[core]: https://ocsigen.org/lwt/latest/api/Lwt +[cond]: https://ocsigen.org/lwt/latest/api/Lwt_condition +[mutex]: https://ocsigen.org/lwt/latest/api/Lwt_mutex +[mvar]: https://ocsigen.org/lwt/latest/api/Lwt_mvar +[unix]: https://ocsigen.org/lwt/latest/api/Lwt_unix +[io]: https://ocsigen.org/lwt/latest/api/Lwt_io +[process]: https://ocsigen.org/lwt/latest/api/Lwt_process +[preemptive]: https://ocsigen.org/lwt/latest/api/Lwt_preemptive +[ppx]: https://ocsigen.org/lwt/latest/api/Ppx_lwt +[react]: https://ocsigen.org/lwt/latest/api/Lwt_react + + +
+ +## Installing + +1. Use your system package manager to install a development libev package. + It is often called `libev-dev` or `libev-devel`. +2. `opam install conf-libev lwt` + + +
+ +## Documentation + +We are currently working on improving the Lwt documentation (drastically; we are +rewriting the manual). In the meantime: + +- The current manual can be found [here][manual]. +- Mirage has a nicely-written [Lwt tutorial][mirage-tutorial]. +- An example of a [simple server][counter-server] written in Lwt. +- [Concurrent Programming with Lwt][rwo-lwt] is a nice source of Lwt examples. + They are translations of code from the excellent Real World OCaml, but are + just as useful if you are not reading the book. + +*Note: much of the current manual refers to `'a Lwt.t` as "lightweight threads" +or just "threads." This will be fixed in the new manual. `'a Lwt.t` is a +promise, and has nothing to do with system or preemptive threads.* + +[manual]: http://ocsigen.org/lwt/ +[rwo-lwt]: https://github.com/dkim/rwo-lwt#readme +[mirage-tutorial]: https://mirage.io/docs/tutorial-lwt +[counter-server]: http://www.baturin.org/code/lwt-counter-server/ + + +
+ +## Contact + +Open an [issue][issues], visit [Discord][discord] chat, ask on +[discuss.ocaml.org][discourse], or on [Stack Overflow][so]. + +Release announcements are made in [/r/ocaml][reddit], and on +[discuss.ocaml.org][discourse]. Watching the repo for "Releases only" is also an +option. + +[irc]: http://webchat.freenode.net/?channels=#ocaml +[so]: http://stackoverflow.com/questions/ask?tags=ocaml,lwt,ocaml-lwt +[announcements]: https://github.com/ocsigen/lwt/issues/309 +[reddit]: https://www.reddit.com/r/ocaml/ +[caml-list]: https://sympa.inria.fr/sympa/arc/caml-list +[discourse]: https://discuss.ocaml.org/tag/lwt +[issues]: https://github.com/ocsigen/lwt/issues/new +[discord]: https://discordapp.com/invite/cCYQbqN + + +
+ +## Contributing + +- [`CONTRIBUTING.md`][contributing-md] contains tips for working on the code, + such as how to check the code out, how review works, etc. There is also a + high-level outline of the code base. +- [Ask](#contact) us anything, whether it's about working on Lwt, or any + question at all about it :) +- The [documentation](#documentation) always needs proofreading and fixes. +- You are welcome to pick up any other [issue][issues-and-prs], review a PR, add + your opinion, etc. +- Any feedback is welcome, including how to make contributing easier! + +[issues-and-prs]: https://github.com/ocsigen/lwt/issues?utf8=%E2%9C%93&q=is%3Aopen +[all-issues]: https://github.com/ocsigen/lwt/issues +[contributing-md]: https://github.com/ocsigen/lwt/blob/master/docs/CONTRIBUTING.md#readme + + +
+ +## Libraries to use with Lwt + +- [alcotest](https://github.com/mirage/alcotest/) β€” +unit testing +- [angstrom](https://github.com/inhabitedtype/angstrom) β€” +parser combinators +- [cohttp](https://github.com/mirage/ocaml-cohttp) β€” HTTP client and server +- [cstruct](https://github.com/mirage/ocaml-cstruct) β€” +interop with C-like structures +- [ezjsonm](https://github.com/mirage/ezjsonm) β€” +JSON parsing and output +- [faraday](https://github.com/inhabitedtype/faraday) β€” +serialization combinators +- [logs](https://github.com/dbuenzli/logs) β€” +logging +- [lwt-parallel](https://github.com/ivg/parallel) β€” +distributed computing +- [mwt](https://github.com/hcarty/mwt) β€” preemptive (system) thread pools +- [opium](https://github.com/rgrinberg/opium) β€” +web framework diff --git a/dev/lwt/_doc-dir/odoc-pages/index.mld b/dev/lwt/_doc-dir/odoc-pages/index.mld new file mode 100644 index 00000000..238f380f --- /dev/null +++ b/dev/lwt/_doc-dir/odoc-pages/index.mld @@ -0,0 +1,131 @@ +{0 Lwt} + +{1 Introduction} + +Lwt is a concurrent programming library for OCaml. It provides a single data +type: the {e promise}, which is a value that will become determined in the +future. Creating a promise spawns a computation. When that computation is I/O, +Lwt runs it in parallel with your OCaml code. + +OCaml code, including creating and waiting on promises, is run in a single +thread by default, so you don't have to worry about locking or preemption. You +can detach code to be run in separate threads on an opt-in basis. + +Here is a simplistic Lwt program which requests the Google front page, and fails +if the request is not completed in five seconds: + +{[ +open Lwt.Syntax + +let () = + let request = + let* addresses = Lwt_unix.getaddrinfo "google.com" "80" [] in + let google = Lwt_unix.((List.hd addresses).ai_addr) in + + Lwt_io.(with_connection google (fun (incoming, outgoing) -> + let* () = write outgoing "GET / HTTP/1.1\r\n" in + let* () = write outgoing "Connection: close\r\n\r\n" in + let* response = read incoming in + Lwt.return (Some response))) + in + + let timeout = + let* () = Lwt_unix.sleep 5. in + Lwt.return None + in + + match Lwt_main.run (Lwt.pick [request; timeout]) with + | Some response -> print_string response + | None -> prerr_endline "Request timed out"; exit 1 + +(* ocamlfind opt -package lwt.unix -linkpkg example.ml && ./a.out *) +]} + +In the program, functions such as [Lwt_io.write] create promises. The +[let%lwt ... in] construct is used to wait for a promise to become determined; +the code after [in] is scheduled to run in a "callback." [Lwt.pick] races +promises against each other, and behaves as the first one to complete. +[Lwt_main.run] forces the whole promise-computation network to be executed. All +the visible OCaml code is run in a single thread, but Lwt internally uses a +combination of worker threads and non-blocking file descriptors to resolve in +parallel the promises that do I/O. + + + +{1 Tour} + +Lwt compiles to native code on Linux, macOS, Windows, and other systems. It's +also routinely compiled to JavaScript for the front end and Node by js_of_ocaml. + +In Lwt, + +- The core library {!Lwt} provides promises... +- ...and a few pure-OCaml helpers, such as promise-friendly {{!Lwt_mutex} + mutexes}, {{!Lwt_condition} condition variables}, and {{!Lwt_mvar} mvars}. +- There is a big Unix binding, {!Lwt_unix}, that binds almost every Unix system + call. A higher-level module {!Lwt_io} provides nice I/O channels. +- {!Lwt_process} is for subprocess handling. +- {!Lwt_preemptive} spawns system threads. + + + +{1 Installing} + ++ Use your system package manager to install a development libev package. It is + often called [libev-dev] or [libev-devel]. ++ [opam install conf-libev lwt] + + + +{1 Additional Docs} + +- {{:http://ocsigen.org/lwt/} Online manual}. +- {{:https://github.com/dkim/rwo-lwt#readme} Concurrent Programming with Lwt} is + a nice source of Lwt examples. They are translations of code from Real World + OCaml, but are just as useful if you are not reading the book. +- {{:https://mirage.io/wiki/tutorial-lwt} Mirage Lwt tutorial}. +- {{:http://www.baturin.org/code/lwt-counter-server/} Example server} written + with Lwt. + + + +{1 API: Library [lwt]} + +This is the system-independent, pure-OCaml core of Lwt. To link with it, use +[(libraries lwt)] in your [dune] file. + +{!modules: + Lwt + Lwt_list + Lwt_stream + Lwt_result + Lwt_mutex + Lwt_condition + Lwt_mvar + Lwt_switch + Lwt_pool +} + + + +{1 API: Library [lwt.unix]} + +This is the system call and I/O library. Despite its name, it is implemented on +both Unix-like systems and Windows, although not all functions are available on +Windows. To link with this library, use [(libraries lwt.unix)] in your [dune] +file. + +{!modules: + Lwt_unix + Lwt_main + Lwt_io + Lwt_process + Lwt_bytes + Lwt_preemptive + Lwt_fmt + Lwt_throttle + Lwt_timeout + Lwt_engine + Lwt_gc + Lwt_sys +} diff --git a/dev/lwt/index.html b/dev/lwt/index.html new file mode 100644 index 00000000..ff5e727c --- /dev/null +++ b/dev/lwt/index.html @@ -0,0 +1,25 @@ + +index (lwt.index)

Package lwt

Introduction

Lwt is a concurrent programming library for OCaml. It provides a single data type: the promise, which is a value that will become determined in the future. Creating a promise spawns a computation. When that computation is I/O, Lwt runs it in parallel with your OCaml code.

OCaml code, including creating and waiting on promises, is run in a single thread by default, so you don't have to worry about locking or preemption. You can detach code to be run in separate threads on an opt-in basis.

Here is a simplistic Lwt program which requests the Google front page, and fails if the request is not completed in five seconds:

open Lwt.Syntax
+
+let () =
+  let request =
+    let* addresses = Lwt_unix.getaddrinfo "google.com" "80" [] in
+    let google = Lwt_unix.((List.hd addresses).ai_addr) in
+
+    Lwt_io.(with_connection google (fun (incoming, outgoing) ->
+      let* () = write outgoing "GET / HTTP/1.1\r\n" in
+      let* () = write outgoing "Connection: close\r\n\r\n" in
+      let* response = read incoming in
+      Lwt.return (Some response)))
+  in
+
+  let timeout =
+    let* () = Lwt_unix.sleep 5. in
+    Lwt.return None
+  in
+
+  match Lwt_main.run (Lwt.pick [request; timeout]) with
+  | Some response -> print_string response
+  | None -> prerr_endline "Request timed out"; exit 1
+
+(* ocamlfind opt -package lwt.unix -linkpkg example.ml && ./a.out *)

In the program, functions such as Lwt_io.write create promises. The let%lwt ... in construct is used to wait for a promise to become determined; the code after in is scheduled to run in a "callback." Lwt.pick races promises against each other, and behaves as the first one to complete. Lwt_main.run forces the whole promise-computation network to be executed. All the visible OCaml code is run in a single thread, but Lwt internally uses a combination of worker threads and non-blocking file descriptors to resolve in parallel the promises that do I/O.

Tour

Lwt compiles to native code on Linux, macOS, Windows, and other systems. It's also routinely compiled to JavaScript for the front end and Node by js_of_ocaml.

In Lwt,

Installing

  1. Use your system package manager to install a development libev package. It is often called libev-dev or libev-devel.
  2. opam install conf-libev lwt

Additional Docs

API: Library lwt

This is the system-independent, pure-OCaml core of Lwt. To link with it, use (libraries lwt) in your dune file.

API: Library lwt.unix

This is the system call and I/O library. Despite its name, it is implemented on both Unix-like systems and Windows, although not all functions are available on Windows. To link with this library, use (libraries lwt.unix) in your dune file.

Package info

changes-files
license-files
readme-files
diff --git a/dev/moonpool-lwt/Moonpool_lwt/IO/index.html b/dev/moonpool-lwt/Moonpool_lwt/IO/index.html new file mode 100644 index 00000000..2c553790 --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt/IO/index.html @@ -0,0 +1,2 @@ + +IO (moonpool-lwt.Moonpool_lwt.IO)

Module Moonpool_lwt.IO

IO using the Lwt event loop.

These IO operations work on non-blocking file descriptors and rely on a Lwt_engine event loop being active (meaning, Lwt_main.run is currently running in some thread).

Calling these functions must be done from a moonpool runner. A function like read will first try to perform the IO action directly (here, call Unix.read); if the action fails because the FD is not ready, then await_readable is called: it suspends the fiber and subscribes it to Lwt to be awakened when the FD becomes ready.

val read : Unix.file_descr -> bytes -> int -> int -> int

Read from the file descriptor

val await_readable : Unix.file_descr -> unit

Suspend the fiber until the FD is readable

val write_once : Unix.file_descr -> bytes -> int -> int -> int

Perform one write into the file descriptor

val await_writable : Unix.file_descr -> unit

Suspend the fiber until the FD is writable

val write : Unix.file_descr -> bytes -> int -> int -> unit

Loop around write_once to write the entire slice.

val sleep_s : float -> unit

Suspend the fiber for n seconds.

diff --git a/dev/moonpool-lwt/Moonpool_lwt/IO_in/class-type-t/index.html b/dev/moonpool-lwt/Moonpool_lwt/IO_in/class-type-t/index.html new file mode 100644 index 00000000..6d550666 --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt/IO_in/class-type-t/index.html @@ -0,0 +1,2 @@ + +t (moonpool-lwt.Moonpool_lwt.IO_in.t)

Class type IO_in.t

method input : bytes -> int -> int -> int

Read into the slice. Returns 0 only if the stream is closed.

method close : unit -> unit

Close the input. Must be idempotent.

diff --git a/dev/moonpool-lwt/Moonpool_lwt/IO_in/index.html b/dev/moonpool-lwt/Moonpool_lwt/IO_in/index.html new file mode 100644 index 00000000..275399db --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt/IO_in/index.html @@ -0,0 +1,6 @@ + +IO_in (moonpool-lwt.Moonpool_lwt.IO_in)

Module Moonpool_lwt.IO_in

Input channel

class type t = object ... end
val create : + ?close:(unit -> unit) -> + input:(bytes -> int -> int -> int) -> + unit -> + t
val empty : t
val of_bytes : ?off:int -> ?len:int -> bytes -> t
val of_string : ?off:int -> ?len:int -> string -> t
val input : t -> bytes -> int -> int -> int

Read into the given slice.

  • returns

    the number of bytes read, 0 means end of input.

val close : < close : unit -> unit.. > -> unit

Close the channel.

val really_input : t -> bytes -> int -> int -> unit
val really_input_string : t -> int -> string
val copy_into : ?buf:bytes -> t -> IO_out.t -> unit
val concat : t list -> t
val input_all : ?buf:bytes -> t -> string
val of_unix_fd : ?close_noerr:bool -> ?buf:bytes -> Unix.file_descr -> t
diff --git a/dev/moonpool-lwt/Moonpool_lwt/IO_out/class-type-t/index.html b/dev/moonpool-lwt/Moonpool_lwt/IO_out/class-type-t/index.html new file mode 100644 index 00000000..84224ff3 --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt/IO_out/class-type-t/index.html @@ -0,0 +1,2 @@ + +t (moonpool-lwt.Moonpool_lwt.IO_out.t)

Class type IO_out.t

method output_char : char -> unit
method output : bytes -> int -> int -> unit
method flush : unit -> unit
method close : unit -> unit
diff --git a/dev/moonpool-lwt/Moonpool_lwt/IO_out/index.html b/dev/moonpool-lwt/Moonpool_lwt/IO_out/index.html new file mode 100644 index 00000000..033e1c16 --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt/IO_out/index.html @@ -0,0 +1,8 @@ + +IO_out (moonpool-lwt.Moonpool_lwt.IO_out)

Module Moonpool_lwt.IO_out

Output channel

class type t = object ... end
val create : + ?flush:(unit -> unit) -> + ?close:(unit -> unit) -> + output_char:(char -> unit) -> + output:(bytes -> int -> int -> unit) -> + unit -> + t
val dummy : t
val of_unix_fd : ?close_noerr:bool -> ?buf:bytes -> Unix.file_descr -> t
val of_buffer : Stdlib.Buffer.t -> t
val output_char : t -> char -> unit

Output the buffer slice into this channel

val output : t -> bytes -> int -> int -> unit

Output the buffer slice into this channel

val output_string : t -> string -> unit
val output_line : t -> string -> unit
val close : < close : unit -> unit.. > -> unit

Close the channel.

val flush : < flush : unit -> unit.. > -> unit

Flush (ie. force write) any buffered bytes.

val output_int : t -> int -> unit
val output_lines : t -> string Stdlib.Seq.t -> unit
val tee : t list -> t
diff --git a/dev/moonpool-lwt/Moonpool_lwt/TCP_client/index.html b/dev/moonpool-lwt/Moonpool_lwt/TCP_client/index.html new file mode 100644 index 00000000..1a21a71e --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt/TCP_client/index.html @@ -0,0 +1,5 @@ + +TCP_client (moonpool-lwt.Moonpool_lwt.TCP_client)

Module Moonpool_lwt.TCP_client

val with_connect : Unix.sockaddr -> (IO_in.t -> IO_out.t -> 'a) -> 'a

Open a connection, and use IO to read and write from the socket in a non blocking way.

val with_connect_lwt : + Unix.sockaddr -> + (Lwt_io.input_channel -> Lwt_io.output_channel -> 'a) -> + 'a

Open a connection.

diff --git a/dev/moonpool-lwt/Moonpool_lwt/TCP_server/index.html b/dev/moonpool-lwt/Moonpool_lwt/TCP_server/index.html new file mode 100644 index 00000000..f2391e4c --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt/TCP_server/index.html @@ -0,0 +1,14 @@ + +TCP_server (moonpool-lwt.Moonpool_lwt.TCP_server)

Module Moonpool_lwt.TCP_server

type t = Lwt_io.server
val establish_lwt : + ?backlog:int -> + ?no_close:bool -> + runner:Moonpool.Runner.t -> + Unix.sockaddr -> + (Unix.sockaddr -> Lwt_io.input_channel -> Lwt_io.output_channel -> unit) -> + t

establish ~runner addr handler runs a TCP server in the Lwt thread. When a client connects, a moonpool fiber is started on runner to handle it.

val establish : + ?backlog:int -> + ?no_close:bool -> + runner:Moonpool.Runner.t -> + Unix.sockaddr -> + (Unix.sockaddr -> IO_in.t -> IO_out.t -> unit) -> + t

Like establish_lwt but uses IO to directly handle reads and writes on client sockets.

val shutdown : t -> unit

Shutdown the server

diff --git a/dev/moonpool-lwt/Moonpool_lwt/index.html b/dev/moonpool-lwt/Moonpool_lwt/index.html new file mode 100644 index 00000000..dea9daa8 --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt/index.html @@ -0,0 +1,2 @@ + +Moonpool_lwt (moonpool-lwt.Moonpool_lwt)

Module Moonpool_lwt

Lwt_engine-based event loop for Moonpool.

In what follows, we mean by "lwt thread" the thread running Lwt_main.run (so, the thread where the Lwt event loop and all Lwt callbacks execute).

  • since NEXT_RELEASE
module Fiber = Moonpool_fib.Fiber
module FLS = Moonpool_fib.Fls

Basic conversions

val fut_of_lwt : 'a Lwt.t -> 'a Moonpool.Fut.t

fut_of_lwt lwt_fut makes a thread-safe moonpool future that completes when lwt_fut does. This must be run from within the Lwt thread.

val lwt_of_fut : 'a Moonpool.Fut.t -> 'a Lwt.t

lwt_of_fut fut makes a lwt future that completes when fut does. This must be called from the Lwt thread, and the result must always be used only from inside the Lwt thread.

Helpers on the moonpool side

val await_lwt : 'a Lwt.t -> 'a

await_lwt fut awaits a Lwt future from inside a task running on a moonpool runner. This must be run from within a Moonpool runner so that the await-ing effect is handled.

val run_in_lwt : (unit -> 'a Lwt.t) -> 'a Moonpool.Fut.t

run_in_lwt f runs f() from within the Lwt thread and returns a thread-safe future. This can be run from anywhere.

val run_in_lwt_and_await : (unit -> 'a Lwt.t) -> 'a

run_in_lwt_and_await f runs f in the Lwt thread, and awaits its result. Must be run from inside a moonpool runner so that the await-in effect is handled.

This is similar to Moonpool.await @@ run_in_lwt f.

val get_runner : unit -> Moonpool.Runner.t

Returns the runner from within which this is called. Must be run from within a fiber.

  • raises Failure

    if not run within a fiber

IO

module IO : sig ... end

IO using the Lwt event loop.

module IO_in : sig ... end

Input channel

module IO_out : sig ... end

Output channel

module TCP_server : sig ... end
module TCP_client : sig ... end

Helpers on the lwt side

val detach_in_runner : runner:Moonpool.Runner.t -> (unit -> 'a) -> 'a Lwt.t

detach_in_runner ~runner f runs f in the given moonpool runner, and returns a lwt future. This must be run from within the thread running Lwt_main.

Wrappers around Lwt_main

val main_with_runner : runner:Moonpool.Runner.t -> (unit -> 'a) -> 'a

main_with_runner ~runner f starts a Lwt-based event loop and runs f() inside a fiber in runner.

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

Like main_with_runner but with a default choice of runner.

diff --git a/dev/moonpool-lwt/Moonpool_lwt__/index.html b/dev/moonpool-lwt/Moonpool_lwt__/index.html new file mode 100644 index 00000000..65a86e82 --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt__/index.html @@ -0,0 +1,2 @@ + +Moonpool_lwt__ (moonpool-lwt.Moonpool_lwt__)

Module Moonpool_lwt__

This module is hidden.

diff --git a/dev/moonpool-lwt/Moonpool_lwt__Base/index.html b/dev/moonpool-lwt/Moonpool_lwt__Base/index.html new file mode 100644 index 00000000..109d96c6 --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt__Base/index.html @@ -0,0 +1,2 @@ + +Moonpool_lwt__Base (moonpool-lwt.Moonpool_lwt__Base)

Module Moonpool_lwt__Base

This module is hidden.

diff --git a/dev/moonpool-lwt/Moonpool_lwt__IO/index.html b/dev/moonpool-lwt/Moonpool_lwt__IO/index.html new file mode 100644 index 00000000..449ecb28 --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt__IO/index.html @@ -0,0 +1,2 @@ + +Moonpool_lwt__IO (moonpool-lwt.Moonpool_lwt__IO)

Module Moonpool_lwt__IO

This module is hidden.

diff --git a/dev/moonpool-lwt/Moonpool_lwt__IO_in/index.html b/dev/moonpool-lwt/Moonpool_lwt__IO_in/index.html new file mode 100644 index 00000000..58803cf9 --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt__IO_in/index.html @@ -0,0 +1,2 @@ + +Moonpool_lwt__IO_in (moonpool-lwt.Moonpool_lwt__IO_in)

Module Moonpool_lwt__IO_in

This module is hidden.

diff --git a/dev/moonpool-lwt/Moonpool_lwt__IO_out/index.html b/dev/moonpool-lwt/Moonpool_lwt__IO_out/index.html new file mode 100644 index 00000000..0f84a0d7 --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt__IO_out/index.html @@ -0,0 +1,2 @@ + +Moonpool_lwt__IO_out (moonpool-lwt.Moonpool_lwt__IO_out)

Module Moonpool_lwt__IO_out

This module is hidden.

diff --git a/dev/moonpool-lwt/Moonpool_lwt__Tcp_client/index.html b/dev/moonpool-lwt/Moonpool_lwt__Tcp_client/index.html new file mode 100644 index 00000000..1a8f8e39 --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt__Tcp_client/index.html @@ -0,0 +1,2 @@ + +Moonpool_lwt__Tcp_client (moonpool-lwt.Moonpool_lwt__Tcp_client)

Module Moonpool_lwt__Tcp_client

This module is hidden.

diff --git a/dev/moonpool-lwt/Moonpool_lwt__Tcp_server/index.html b/dev/moonpool-lwt/Moonpool_lwt__Tcp_server/index.html new file mode 100644 index 00000000..26f4b28d --- /dev/null +++ b/dev/moonpool-lwt/Moonpool_lwt__Tcp_server/index.html @@ -0,0 +1,2 @@ + +Moonpool_lwt__Tcp_server (moonpool-lwt.Moonpool_lwt__Tcp_server)

Module Moonpool_lwt__Tcp_server

This module is hidden.

diff --git a/dev/moonpool-lwt/_doc-dir/CHANGES.md b/dev/moonpool-lwt/_doc-dir/CHANGES.md new file mode 100644 index 00000000..3e855a20 --- /dev/null +++ b/dev/moonpool-lwt/_doc-dir/CHANGES.md @@ -0,0 +1,103 @@ + +# 0.5.1 + +- fix `Ws_pool`: workers would exit before processing + all remaining tasks upon shutdown + +# 0.5 + +## features + +- add `Bb_queue.transfer` +- add `Bb_queue.to_{iter,gen,seq}` +- add `Fifo_pool`, a simple pool with a single blocking queue for + workloads with coarse granularity tasks that value + latency (e.g. a web server) +- add a work-stealing pool for heavy compute workloads that + feature a lot of await/fork-join, with a lot of help + from Vesa Karvonen (@polytypic) +- add `Fut.spawn_on_current_runner` +- add `Runner.{spawn_on_current_runner, await}` +- add a few more toplevel aliases in `Moonpool` itself +- add `No_runner`: a runner that runs tasks synchronously in the caller +- on shutdown, pools will finish running all present tasks before + closing. New tasks are immediately rejected. + +- use an optional dependency on `thread-local-storage` to + implement work stealing and `spawn_on_current_runner` + +## optimizations + +- use the main domain to spawn threads on it. This means we can really + use all cores, not all but one. +- in `Fork_join.both`, only one of the two sides schedules a task, + the other runs in the current thread. This reduces scheduling overhead. +- compare to domainslib in benchmarks. With the WS pool we're now slightly + ahead in terms of overhead on the recursive fib benchmark. + +## breaking + +- deprecate `Pool`, now an alias to `Fifo_pool` +- the `Fut.Infix_local` and `Fut.infix` are gone, replaced with + a simpler `Fut.Infix` module that tries to use the current runner + for intermediate tasks. + +# 0.4 + +- add `Fut.{reify_error,bind_reify_error}` +- full lifecycle for worker domains, where a domain + will shutdown if no thread runs on it, after a + short delay. + +- fix: generalize type of `create_arg` +- perf: in `Bb_queue`, only signal condition on push if queue was empty + +# 0.3 + +- add `Fork_join` for parallelizing computations. This is only + available on OCaml 5.x because it relies on effects. +- add `Fork_join.{for_,map_array,map_list}` +- add `Fork_join.all_{list,init}` +- add `Pool.with_` +- add a channel module +- add `Runner`, change `Pool` to produce a `Runner.t` +- add a `Lock` module +- add support for domain-local-await when installed +- add `Fut.await` for OCaml >= 5.0 + +- fix: Fork_join.both_ignore now has a more general type + +- expose `Suspend_` and its internal effect with an unstability alert. + This is intended for implementors of `Runner` only. +- port `cpp.ml` from containers, replace previous codegen with it. + This will provide better flexibility for supporting multiple versions + of OCaml in the future. +- add `Pool.run_wait_block`; rename `Pool.run` into `Pool.run_async` +- fix: in blocking queue, `pop` works on a non empty closed queue + +# 0.2 + +- add `Fut.for_list` +- add `around_task` to `Pool.create` +- add `Pool.shutdown_without_waiting` +- add `Pool.num_tasks` +- add `Fut.is_done` +- add `Blocking_queue.size` +- add `Fut.for_array` to easily iterate on an array in parallel +- add `Fut.get_or_fail{,_exn}` + +- perf: limit number of work queues in pool +- perf: use multiple queues and non-blocking work-stealing from them, in pool + this improves the behavior for many small tasks by reducing contention on + each queue + +- fix: fut: actually run all map/bind callbacks in pool if provided + +# 0.1.1 + +- fix(fut): fix bug when calling `wait_list []` +- fix: join_array on arrays of length=1 had a bound error + +# 0.1 + +initial release diff --git a/dev/moonpool-lwt/_doc-dir/README.md b/dev/moonpool-lwt/_doc-dir/README.md new file mode 100644 index 00000000..c51361df --- /dev/null +++ b/dev/moonpool-lwt/_doc-dir/README.md @@ -0,0 +1,313 @@ +# Moonpool + +[![build](https://github.com/c-cube/moonpool/actions/workflows/main.yml/badge.svg)](https://github.com/c-cube/moonpool/actions/workflows/main.yml) + +A pool within a bigger pool (ie the ocean). Here, we're talking about +pools of `Thread.t` which live within a fixed pool of `Domain.t`. + +This fixed pool of domains is shared between *all* the pools in moonpool. +The rationale is that we should not have more domains than cores, so +it's easier to pre-allocate exactly that many domains, and run more flexible +thread pools on top. + +In addition, some concurrency and parallelism primitives are provided: +- `Moonpool.Fut` provides futures/promises that execute + on these thread pools. The futures are thread safe. +- `Moonpool.Chan` provides simple cooperative and thread-safe channels + to use within pool-bound tasks. They're essentially re-usable futures. + + On OCaml 5 (meaning there's actual domains and effects, not just threads), + a `Fut.await` primitive is provided. It's simpler and more powerful + than the monadic combinators. +- `Moonpool_forkjoin`, in the library `moonpool.forkjoin` + provides the fork-join parallelism primitives + to use within tasks running in the pool. + +## Usage + +The user can create several thread pools (implementing the interface `Runner.t`). +These pools use regular posix threads, but the threads are spread across +multiple domains (on OCaml 5), which enables parallelism. + +Current we provide these pool implementations: +- `Fifo_pool` is a thread pool that uses a blocking queue to schedule tasks, + which means they're picked in the same order they've been scheduled ("fifo"). + This pool is simple and will behave fine for coarse-granularity concurrency, + but will slow down under heavy contention. +- `Ws_pool` is a work-stealing pool, where each thread has its own local queue + in addition to a global queue of tasks. This is efficient for workloads + with many short tasks that spawn other tasks, but the order in which + tasks are run is less predictable. This is useful when throughput is + the important thing to optimize. + +The function `Runner.run_async pool task` schedules `task()` to run on one of +the workers of `pool`, as soon as one is available. No result is returned by `run_async`. + +```ocaml +# #require "threads";; +# let pool = Moonpool.Fifo_pool.create ~num_threads:4 ();; +val pool : Moonpool.Runner.t = + +# begin + Moonpool.Runner.run_async pool + (fun () -> + Thread.delay 0.1; + print_endline "running from the pool"); + print_endline "running from the caller"; + Thread.delay 0.3; (* wait for task to run before returning *) + end ;; +running from the caller +running from the pool +- : unit = () +``` + +To wait until the task is done, you can use `Runner.run_wait_block`[^1] instead: + +[^1]: beware of deadlock! See documentation for more details. + +```ocaml +# begin + Moonpool.Runner.run_wait_block pool + (fun () -> + Thread.delay 0.1; + print_endline "running from the pool"); + print_endline "running from the caller (after waiting)"; + end ;; +running from the pool +running from the caller (after waiting) +- : unit = () +``` + +The function `Fut.spawn ~on f` schedules `f ()` on the pool `on`, and immediately +returns a _future_ which will eventually hold the result (or an exception). + +The function `Fut.peek` will return the current value, or `None` if the future is +still not completed. +The functions `Fut.wait_block` and `Fut.wait_block_exn` will +block the current thread and wait for the future to complete. +There are some deadlock risks associated with careless use of these, so +be sure to consult the documentation of the `Fut` module. + +```ocaml +# let fut = Moonpool.Fut.spawn ~on:pool + (fun () -> + Thread.delay 0.5; + 1+1);; +val fut : int Moonpool.Fut.t = + +# Moonpool.Fut.peek fut; +- : int Moonpool.Fut.or_error option = None + +# Moonpool.Fut.wait_block_exn fut;; +- : int = 2 +``` + +Some combinators on futures are also provided, e.g. to wait for all futures in +an array to complete: + +```ocaml +# let rec fib x = + if x <= 1 then 1 else fib (x-1) + fib (x-2);; +val fib : int -> int = + +# List.init 10 fib;; +- : int list = [1; 1; 2; 3; 5; 8; 13; 21; 34; 55] + +# let fibs = Array.init 35 (fun n -> Moonpool.Fut.spawn ~on:pool (fun () -> fib n));; +val fibs : int Moonpool.Fut.t array = + [|; ; ; ; ; ; ; ; + ; ; ; ; ; ; ; ; + ; ; ; ; ; ; ; ; + ; ; ; ; ; ; ; ; + ; ; |] + +# Moonpool.Fut.join_array fibs |> Moonpool.Fut.wait_block;; +- : int array Moonpool.Fut.or_error = +Ok + [|1; 1; 2; 3; 5; 8; 13; 21; 34; 55; 89; 144; 233; 377; 610; 987; 1597; 2584; + 4181; 6765; 10946; 17711; 28657; 46368; 75025; 121393; 196418; 317811; + 514229; 832040; 1346269; 2178309; 3524578; 5702887; 9227465|] +``` + +### Support for `await` + +On OCaml 5, effect handlers can be used to implement `Fut.await : 'a Fut.t -> 'a`. + +The expression `Fut.await some_fut`, when run from inside some thread pool, +suspends its caller task; the suspended task is then parked, and will +be resumed when the future is completed. +The pool worker that was executing this expression, in the mean time, moves +on to another task. +This means that `await` is free of the deadlock risks associated with +`Fut.wait_block`. + +In the following example, we bypass the need for `Fut.join_array` by simply +using regular array functions along with `Fut.await`. + +```ocaml +# let main_fut = + let open Moonpool.Fut in + spawn ~on:pool @@ fun () -> + (* array of sub-futures *) + let tasks: _ Moonpool.Fut.t array = Array.init 100 (fun i -> + spawn ~on:pool (fun () -> + Thread.delay 0.01; + i+1)) + in + Array.fold_left (fun n fut -> n + await fut) 0 tasks + ;; +val main_fut : int Moonpool.Fut.t = + +# let expected_sum = Array.init 100 (fun i->i+1) |> Array.fold_left (+) 0;; +val expected_sum : int = 5050 + +# assert (expected_sum = Moonpool.Fut.wait_block_exn main_fut);; +- : unit = () +``` + +### Fork-join + +On OCaml 5, again using effect handlers, the sublibrary `moonpool.forkjoin` +provides a module `Moonpool_forkjoin` +implements the [fork-join model](https://en.wikipedia.org/wiki/Fork%E2%80%93join_model). +It must run on a pool (using `Runner.run_async` or inside a future via `Fut.spawn`). + +It is generally better to use the work-stealing pool for workloads that rely on +fork-join for better performance, because fork-join will tend to spawn lots of +shorter tasks. + +Here is an simple example of a parallel sort. +It uses selection sort for small slices, like this: + +```ocaml +# let rec select_sort arr i len = + if len >= 2 then ( + let idx = ref i in + for j = i+1 to i+len-1 do + if arr.(j) < arr.(!idx) then idx := j + done; + let tmp = arr.(!idx) in + arr.(!idx) <- arr.(i); + arr.(i) <- tmp; + select_sort arr (i+1) (len-1) + );; +val select_sort : 'a array -> int -> int -> unit = +``` + +And a parallel quicksort for larger slices: + +```ocaml +# let rec quicksort arr i len : unit = + if len <= 10 then select_sort arr i len + else ( + let pivot = arr.(i + (len / 2)) in + let low = ref (i - 1) in + let high = ref (i + len) in + + (* partition the array slice *) + while !low < !high do + incr low; + decr high; + while arr.(!low) < pivot do + incr low + done; + while arr.(!high) > pivot do + decr high + done; + if !low < !high then ( + let tmp = arr.(!low) in + arr.(!low) <- arr.(!high); + arr.(!high) <- tmp + ) + done; + + (* sort lower half and upper half in parallel *) + Moonpool_forkjoin.both_ignore + (fun () -> quicksort arr i (!low - i)) + (fun () -> quicksort arr !low (len - (!low - i))) + );; +val quicksort : 'a array -> int -> int -> unit = + + +# let arr = [| 4;2;1;5;1;10;3 |];; +val arr : int array = [|4; 2; 1; 5; 1; 10; 3|] +# Moonpool.Fut.spawn + ~on:pool (fun () -> quicksort arr 0 (Array.length arr)) + |> Moonpool.Fut.wait_block_exn;; +- : unit = () +# arr;; +- : int array = [|1; 1; 2; 3; 4; 5; 10|] + + +# let arr = + let rand = Random.State.make [| 42 |] in + Array.init 40 (fun _-> Random.State.int rand 300);; +val arr : int array = + [|64; 220; 247; 196; 51; 186; 22; 106; 58; 58; 11; 161; 243; 111; 74; 109; + 49; 135; 59; 192; 132; 38; 19; 44; 126; 147; 182; 83; 95; 231; 204; 121; + 142; 255; 72; 85; 95; 93; 73; 202|] +# Moonpool.Fut.spawn ~on:pool + (fun () -> quicksort arr 0 (Array.length arr)) + |> Moonpool.Fut.wait_block_exn + ;; +- : unit = () +# arr;; +- : int array = +[|11; 19; 22; 38; 44; 49; 51; 58; 58; 59; 64; 72; 73; 74; 83; 85; 93; 95; 95; + 106; 109; 111; 121; 126; 132; 135; 142; 147; 161; 182; 186; 192; 196; 202; + 204; 220; 231; 243; 247; 255|] +``` + +Note that the sort had to be started in a task (via `Moonpool.Fut.spawn`) +so that fork-join would run on the thread pool. +This is necessary even for the initial iteration because fork-join +relies on OCaml 5's effects, meaning that the computation needs to run +inside an effect handler provided by the thread pool. + +### More intuition + +To quote [gasche](https://discuss.ocaml.org/t/ann-moonpool-0-1/12387/15): + +
+You are assuming that, if pool P1 has 5000 tasks, and pool P2 has 10 other tasks, then these 10 tasks will get to run faster than if we just added them at the end of pool P1. This sounds like a β€œfairness” assumption: separate pools will get comparable shares of domain compute ressources, or at least no pool will be delayed too much from running their first tasks. + +[…] + +- each pool uses a fixed number of threads, all running simultaneously; if there are more tasks sent to the pool, they are delayed and will only get one of the pool threads when previous tasks have finished +- separate pools run their separate threads simultaneously, so they compete for compute resources on their domain using OCaml’s systhreads scheduler – which does provide fairness in practice +- as a result, running in a new pool enables quicker completion than adding to an existing pool (as we will be scheduled right away instead of waiting for previous tasks in our pool to free some threads) +- the ratio of compute resources that each pool gets should be roughly proportional to its number of worker threads +
+ +## OCaml versions + +This works for OCaml >= 4.08. +- On OCaml 4.xx, there are no domains, so this is just a library for regular thread pools + with not actual parallelism (except for threads that call C code that releases the runtime lock, that is). + C calls that do release the runtime lock (e.g. to call [Z3](https://github.com/Z3Prover/z3), hash a file, etc.) + will still run in parallel. +- on OCaml 5.xx, there is a fixed pool of domains (using the recommended domain count). + These domains do not do much by themselves, but we schedule new threads on them, and form pools + of threads that contain threads from each domain. + Each domain might thus have multiple threads that belong to distinct pools (and several threads from + the same pool, too β€” this is useful for threads blocking on IO); Each pool will have threads + running on distinct domains, which enables parallelism. + + A useful analogy is that each domain is a bit like a CPU core, and `Thread.t` is a logical thread running on a core. + Multiple threads have to share a single core and do not run in parallel on it[^2]. + We can therefore build pools that spread their worker threads on multiple cores to enable parallelism within each pool. + +TODO: actually use https://github.com/haesbaert/ocaml-processor to pin domains to cores, +possibly optionally using `select` in dune. + +## License + +MIT license. + +## Install + +```sh, skip +$ opam install moonpool +``` + +[^2]: ignoring hyperthreading for the sake of the analogy. diff --git a/dev/moonpool-lwt/index.html b/dev/moonpool-lwt/index.html new file mode 100644 index 00000000..468ef79d --- /dev/null +++ b/dev/moonpool-lwt/index.html @@ -0,0 +1,2 @@ + +index (moonpool-lwt.index)

Package moonpool-lwt

Package info

changes-files
readme-files
diff --git a/dev/moonpool/Moonpool/Fifo_pool/For_runner_implementors/index.html b/dev/moonpool/Moonpool/Fifo_pool/For_runner_implementors/index.html index e5404afa..a0601776 100644 --- a/dev/moonpool/Moonpool/Fifo_pool/For_runner_implementors/index.html +++ b/dev/moonpool/Moonpool/Fifo_pool/For_runner_implementors/index.html @@ -3,6 +3,6 @@ size:(unit -> int) -> num_tasks:(unit -> int) -> shutdown:(wait:bool -> unit -> unit) -> - run_async:(name:string -> ls:Task_local_storage.storage -> task -> unit) -> + run_async:(ls:Task_local_storage.storage -> task -> unit) -> unit -> t

Create a new runner.

NOTE: the runner should support DLA and Suspend_ on OCaml 5.x, so that Fork_join and other 5.x features work properly.

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 get_current_runner to work.

diff --git a/dev/moonpool/Moonpool/Fifo_pool/index.html b/dev/moonpool/Moonpool/Fifo_pool/index.html index e1fa2b31..173e7644 100644 --- a/dev/moonpool/Moonpool/Fifo_pool/index.html +++ b/dev/moonpool/Moonpool/Fifo_pool/index.html @@ -1,15 +1,5 @@ -Fifo_pool (moonpool.Moonpool.Fifo_pool)

Module Moonpool.Fifo_pool

A simple thread pool in FIFO order.

FIFO: first-in, first-out. Basically tasks are put into a queue, and worker threads pull them out of the queue at the other end.

Since this uses a single blocking queue to manage tasks, it's very simple and reliable. The number of worker threads is fixed, but they are spread over several domains to enable parallelism.

This can be useful for latency-sensitive applications (e.g. as a pool of workers for network servers). Work-stealing pools might have higher throughput but they're very unfair to some tasks; by contrast, here, older tasks have priority over younger tasks.

  • since 0.5
include module type of Runner
type task = unit -> unit
type t

A runner.

If a runner is no longer needed, shutdown can be used to signal all worker threads in it to stop (after they finish their work), and wait for them to stop.

The threads are distributed across a fixed domain pool (whose size is determined by Domain.recommended_domain_count on OCaml 5, and simple the single runtime on OCaml 4).

val size : t -> int

Number of threads/workers.

val num_tasks : t -> int

Current number of tasks. This is at best a snapshot, useful for metrics and debugging.

val shutdown : t -> unit

Shutdown the runner and wait for it to terminate. Idempotent.

val shutdown_without_waiting : t -> unit

Shutdown the pool, and do not wait for it to terminate. Idempotent.

exception Shutdown
val run_async : - ?name:string -> - ?ls:Task_local_storage.storage -> - t -> - task -> - unit

run_async pool f schedules f for later execution on the runner in one of the threads. f() will run on one of the runner's worker threads/domains.

  • parameter name

    if provided and Trace is present in dependencies, a span will be created when the task starts, and will stop when the task is over. (since NEXT_RELEASE)

  • parameter ls

    if provided, run the task with this initial local storage

  • raises Shutdown

    if the runner was shut down before run_async was called.

val run_wait_block : - ?name:string -> - ?ls:Task_local_storage.storage -> - t -> - (unit -> 'a) -> - 'a

run_wait_block pool f schedules f for later execution on the pool, like run_async. It then blocks the current thread until f() is done executing, and returns its result. If f() raises an exception, then run_wait_block pool f will raise it as well.

NOTE be careful with deadlocks (see notes in Fut.wait_block about the required discipline to avoid deadlocks).

  • raises Shutdown

    if the runner was already shut down

Implementing runners

module For_runner_implementors : sig ... end

This module is specifically intended for users who implement their own runners. Regular users of Moonpool should not need to look at it.

val get_current_runner : unit -> t option

Access the current runner. This returns Some r if the call happens on a thread that belongs in a runner.

  • since 0.5
type ('a, 'b) create_args = +Fifo_pool (moonpool.Moonpool.Fifo_pool)

Module Moonpool.Fifo_pool

A simple thread pool in FIFO order.

FIFO: first-in, first-out. Basically tasks are put into a queue, and worker threads pull them out of the queue at the other end.

Since this uses a single blocking queue to manage tasks, it's very simple and reliable. The number of worker threads is fixed, but they are spread over several domains to enable parallelism.

This can be useful for latency-sensitive applications (e.g. as a pool of workers for network servers). Work-stealing pools might have higher throughput but they're very unfair to some tasks; by contrast, here, older tasks have priority over younger tasks.

  • since 0.5
include module type of Runner
type task = unit -> unit
type t

A runner.

If a runner is no longer needed, shutdown can be used to signal all worker threads in it to stop (after they finish their work), and wait for them to stop.

The threads are distributed across a fixed domain pool (whose size is determined by Domain.recommended_domain_count on OCaml 5, and simple the single runtime on OCaml 4).

val size : t -> int

Number of threads/workers.

val num_tasks : t -> int

Current number of tasks. This is at best a snapshot, useful for metrics and debugging.

val shutdown : t -> unit

Shutdown the runner and wait for it to terminate. Idempotent.

val shutdown_without_waiting : t -> unit

Shutdown the pool, and do not wait for it to terminate. Idempotent.

exception Shutdown
val run_async : ?ls:Task_local_storage.storage -> t -> task -> unit

run_async pool f schedules f for later execution on the runner in one of the threads. f() will run on one of the runner's worker threads/domains.

  • parameter ls

    if provided, run the task with this initial local storage

  • raises Shutdown

    if the runner was shut down before run_async was called.

val run_wait_block : ?ls:Task_local_storage.storage -> t -> (unit -> 'a) -> 'a

run_wait_block pool f schedules f for later execution on the pool, like run_async. It then blocks the current thread until f() is done executing, and returns its result. If f() raises an exception, then run_wait_block pool f will raise it as well.

NOTE be careful with deadlocks (see notes in Fut.wait_block about the required discipline to avoid deadlocks).

  • raises Shutdown

    if the runner was already shut down

Implementing runners

module For_runner_implementors : sig ... end

This module is specifically intended for users who implement their own runners. Regular users of Moonpool should not need to look at it.

val get_current_runner : unit -> t option

Access the current runner. This returns Some r if the call happens on a thread that belongs in a runner.

  • since 0.5
type ('a, 'b) create_args = ?on_init_thread:(dom_id:int -> t_id:int -> unit -> unit) -> ?on_exit_thread:(dom_id:int -> t_id:int -> unit -> unit) -> ?on_exn:(exn -> Stdlib.Printexc.raw_backtrace -> unit) -> diff --git a/dev/moonpool/Moonpool/Fut/index.html b/dev/moonpool/Moonpool/Fut/index.html index b4b5b1f8..8d93d42f 100644 --- a/dev/moonpool/Moonpool/Fut/index.html +++ b/dev/moonpool/Moonpool/Fut/index.html @@ -1,11 +1,9 @@ -Fut (moonpool.Moonpool.Fut)

Module Moonpool.Fut

Futures.

A future of type 'a t represents the result of a computation that will yield a value of type 'a.

Typically, the computation is running on a thread pool Runner.t and will proceed on some worker. Once set, a future cannot change. It either succeeds (storing a Ok x with x: 'a), or fail (storing a Error (exn, bt) with an exception and the corresponding backtrace).

Combinators such as map and join_array can be used to produce futures from other futures (in a monadic way). Some combinators take a on argument to specify a runner on which the intermediate computation takes place; for example map ~on:pool ~f fut maps the value in fut using function f, applicatively; the call to f happens on the runner pool (once fut resolves successfully with a value).

type 'a or_error = ('a, Exn_bt.t) result
type 'a t

A future with a result of type 'a.

type 'a promise

A promise, which can be fulfilled exactly once to set the corresponding future

val make : ?name:string -> unit -> 'a t * 'a promise

Make a new future with the associated promise.

  • parameter name

    name for the future, used for tracing. since NEXT_RELEASE.

val on_result : 'a t -> ('a or_error -> unit) -> unit

on_result fut f registers f to be called in the future when fut is set ; or calls f immediately if fut is already set.

exception Already_fulfilled
val fulfill : 'a promise -> 'a or_error -> unit

Fullfill the promise, setting the future at the same time.

val fulfill_idempotent : 'a promise -> 'a or_error -> unit

Fullfill the promise, setting the future at the same time. Does nothing if the promise is already fulfilled.

val return : 'a -> 'a t

Already settled future, with a result

val fail : exn -> Stdlib.Printexc.raw_backtrace -> _ t

Already settled future, with a failure

val fail_exn_bt : Exn_bt.t -> _ t

Fail from a bundle of exception and backtrace

  • since NEXT_RELEASE
val of_result : 'a or_error -> 'a t
val is_resolved : _ t -> bool

is_resolved fut is true iff fut is resolved.

val peek : 'a t -> 'a or_error option

peek fut returns Some r if fut is currently resolved with r, and None if fut is not resolved yet.

exception Not_ready
  • since 0.2
val get_or_fail : 'a t -> 'a or_error

get_or_fail fut obtains the result from fut if it's fulfilled (i.e. if peek fut returns Some res, get_or_fail fut returns res).

  • since 0.2
val get_or_fail_exn : 'a t -> 'a

get_or_fail_exn fut obtains the result from fut if it's fulfilled, like get_or_fail. If the result is an Error _, the exception inside is re-raised.

  • since 0.2
val is_done : _ t -> bool

Is the future resolved? This is the same as peek fut |> Option.is_some.

  • since 0.2
val is_success : _ t -> bool

Checks if the future is resolved with Ok _ as a result.

  • since NEXT_RELEASE
val is_failed : _ t -> bool

Checks if the future is resolved with Error _ as a result.

  • since NEXT_RELEASE

Combinators

val spawn : - ?name:string -> +Fut (moonpool.Moonpool.Fut)

Module Moonpool.Fut

Futures.

A future of type 'a t represents the result of a computation that will yield a value of type 'a.

Typically, the computation is running on a thread pool Runner.t and will proceed on some worker. Once set, a future cannot change. It either succeeds (storing a Ok x with x: 'a), or fail (storing a Error (exn, bt) with an exception and the corresponding backtrace).

Combinators such as map and join_array can be used to produce futures from other futures (in a monadic way). Some combinators take a on argument to specify a runner on which the intermediate computation takes place; for example map ~on:pool ~f fut maps the value in fut using function f, applicatively; the call to f happens on the runner pool (once fut resolves successfully with a value).

type 'a or_error = ('a, Exn_bt.t) result
type 'a t

A future with a result of type 'a.

type 'a promise

A promise, which can be fulfilled exactly once to set the corresponding future

val make : unit -> 'a t * 'a promise

Make a new future with the associated promise.

val on_result : 'a t -> ('a or_error -> unit) -> unit

on_result fut f registers f to be called in the future when fut is set ; or calls f immediately if fut is already set.

exception Already_fulfilled
val fulfill : 'a promise -> 'a or_error -> unit

Fullfill the promise, setting the future at the same time.

val fulfill_idempotent : 'a promise -> 'a or_error -> unit

Fullfill the promise, setting the future at the same time. Does nothing if the promise is already fulfilled.

val return : 'a -> 'a t

Already settled future, with a result

val fail : exn -> Stdlib.Printexc.raw_backtrace -> _ t

Already settled future, with a failure

val fail_exn_bt : Exn_bt.t -> _ t

Fail from a bundle of exception and backtrace

  • since NEXT_RELEASE
val of_result : 'a or_error -> 'a t
val is_resolved : _ t -> bool

is_resolved fut is true iff fut is resolved.

val peek : 'a t -> 'a or_error option

peek fut returns Some r if fut is currently resolved with r, and None if fut is not resolved yet.

exception Not_ready
  • since 0.2
val get_or_fail : 'a t -> 'a or_error

get_or_fail fut obtains the result from fut if it's fulfilled (i.e. if peek fut returns Some res, get_or_fail fut returns res).

  • since 0.2
val get_or_fail_exn : 'a t -> 'a

get_or_fail_exn fut obtains the result from fut if it's fulfilled, like get_or_fail. If the result is an Error _, the exception inside is re-raised.

  • since 0.2
val is_done : _ t -> bool

Is the future resolved? This is the same as peek fut |> Option.is_some.

  • since 0.2
val is_success : _ t -> bool

Checks if the future is resolved with Ok _ as a result.

  • since NEXT_RELEASE
val is_failed : _ t -> bool

Checks if the future is resolved with Error _ as a result.

  • since NEXT_RELEASE

Combinators

val spawn : ?ls:Task_local_storage.storage -> on:Runner.t -> (unit -> 'a) -> 'a t

spaw ~on f runs f() on the given runner on, and return a future that will hold its result.

val spawn_on_current_runner : - ?name:string -> ?ls:Task_local_storage.storage -> (unit -> 'a) -> 'a t

This must be run from inside a runner, and schedules the new task on it as well.

See Runner.get_current_runner to see how the runner is found.

  • since 0.5
  • raises Failure

    if run from outside a runner.

val reify_error : 'a t -> 'a or_error t

reify_error fut turns a failing future into a non-failing one that contain Error (exn, bt). A non-failing future returning x is turned into Ok x

  • since 0.4
val map : ?on:Runner.t -> f:('a -> 'b) -> 'a t -> 'b t

map ?on ~f fut returns a new future fut2 that resolves with f x if fut resolved with x; and fails with e if fut fails with e or f x raises e.

  • parameter on

    if provided, f runs on the given runner

val bind : ?on:Runner.t -> f:('a -> 'b t) -> 'a t -> 'b t

bind ?on ~f fut returns a new future fut2 that resolves like the future f x if fut resolved with x; and fails with e if fut fails with e or f x raises e.

  • parameter on

    if provided, f runs on the given runner

val bind_reify_error : ?on:Runner.t -> f:('a or_error -> 'b t) -> 'a t -> 'b t

bind_reify_error ?on ~f fut returns a new future fut2 that resolves like the future f (Ok x) if fut resolved with x; and resolves like the future f (Error (exn, bt)) if fut fails with exn and backtrace bt.

  • parameter on

    if provided, f runs on the given runner

  • since 0.4
val join : 'a t t -> 'a t

join fut is fut >>= Fun.id. It joins the inner layer of the future.

  • since 0.2
val both : 'a t -> 'b t -> ('a * 'b) t

both a b succeeds with x, y if a succeeds with x and b succeeds with y, or fails if any of them fails.

val choose : 'a t -> 'b t -> ('a, 'b) Either.t t

choose a b succeeds Left x or Right y if a succeeds with x or b succeeds with y, or fails if both of them fails. If they both succeed, it is not specified which result is used.

val choose_same : 'a t -> 'a t -> 'a t

choose_same a b succeeds with the value of one of a or b if they succeed, or fails if both fail. If they both succeed, it is not specified which result is used.

val join_array : 'a t array -> 'a array t

Wait for all the futures in the array. Fails if any future fails.

val join_list : 'a t list -> 'a list t

Wait for all the futures in the list. Fails if any future fails.

module Advanced : sig ... end
val map_list : f:('a -> 'b t) -> 'a list -> 'b list t

map_list ~f l is like join_list @@ List.map f l.

  • since 0.5.1
val wait_array : _ t array -> unit t

wait_array arr waits for all futures in arr to resolve. It discards the individual results of futures in arr. It fails if any future fails.

val wait_list : _ t list -> unit t

wait_list l waits for all futures in l to resolve. It discards the individual results of futures in l. It fails if any future fails.

val for_ : on:Runner.t -> int -> (int -> unit) -> unit t

for_ ~on n f runs f 0, f 1, …, f (n-1) on the runner, and returns a future that resolves when all the tasks have resolved, or fails as soon as one task has failed.

val for_array : on:Runner.t -> 'a array -> (int -> 'a -> unit) -> unit t

for_array ~on arr f runs f 0 arr.(0), …, f (n-1) arr.(n-1) in the runner (where n = Array.length arr), and returns a future that resolves when all the tasks are done, or fails if any of them fails.

  • since 0.2
val for_list : on:Runner.t -> 'a list -> ('a -> unit) -> unit t

for_list ~on l f is like for_array ~on (Array.of_list l) f.

  • since 0.2

Await

NOTE This is only available on OCaml 5.

val await : 'a t -> 'a

await fut suspends the current tasks until fut is fulfilled, then resumes the task on this same runner (but possibly on a different thread/domain).

  • since 0.3

This must only be run from inside the runner itself. The runner must support Suspend_. NOTE: only on OCaml 5.x

Blocking

val wait_block : 'a t -> 'a or_error

wait_block fut blocks the current thread until fut is resolved, and returns its value.

NOTE: A word of warning: this will monopolize the calling thread until the future resolves. This can also easily cause deadlocks, if enough threads in a pool call wait_block on futures running on the same pool or a pool depending on it.

A good rule to avoid deadlocks is to run this from outside of any pool, or to have an acyclic order between pools where wait_block is only called from a pool on futures evaluated in a pool that comes lower in the hierarchy. If this rule is broken, it is possible for all threads in a pool to wait for futures that can only make progress on these same threads, hence the deadlock.

val wait_block_exn : 'a t -> 'a

Same as wait_block but re-raises the exception if the future failed.

Infix operators

These combinators run on either the current pool (if present), or on the same thread that just fulfilled the previous future if not.

They were previously present as module Infix_local and val infix, but are now simplified.

  • since 0.5
module Infix : sig ... end
include module type of Infix
  • since 0.5
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
val let+ : 'a t -> ('a -> 'b) -> 'b t
val and+ : 'a t -> 'b t -> ('a * 'b) t
val let* : 'a t -> ('a -> 'b t) -> 'b t
val and* : 'a t -> 'b t -> ('a * 'b) t
module Infix_local = Infix
diff --git a/dev/moonpool/Moonpool/Immediate_runner/For_runner_implementors/index.html b/dev/moonpool/Moonpool/Immediate_runner/For_runner_implementors/index.html index e99177a1..31922564 100644 --- a/dev/moonpool/Moonpool/Immediate_runner/For_runner_implementors/index.html +++ b/dev/moonpool/Moonpool/Immediate_runner/For_runner_implementors/index.html @@ -3,6 +3,6 @@ size:(unit -> int) -> num_tasks:(unit -> int) -> shutdown:(wait:bool -> unit -> unit) -> - run_async:(name:string -> ls:Task_local_storage.storage -> task -> unit) -> + run_async:(ls:Task_local_storage.storage -> task -> unit) -> unit -> t

Create a new runner.

NOTE: the runner should support DLA and Suspend_ on OCaml 5.x, so that Fork_join and other 5.x features work properly.

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 get_current_runner to work.

diff --git a/dev/moonpool/Moonpool/Immediate_runner/index.html b/dev/moonpool/Moonpool/Immediate_runner/index.html index 62fab13e..9c7ded75 100644 --- a/dev/moonpool/Moonpool/Immediate_runner/index.html +++ b/dev/moonpool/Moonpool/Immediate_runner/index.html @@ -1,12 +1,2 @@ -Immediate_runner (moonpool.Moonpool.Immediate_runner)

Module Moonpool.Immediate_runner

Runner that runs tasks immediately in the caller thread.

Whenever a task is submitted to this runner via Runner.run_async r task, the task is run immediately in the caller thread as task(). There are no background threads, no resource, this is just a trivial implementation of the interface.

This can be useful when an implementation needs a runner, but there isn't enough work to justify starting an actual full thread pool.

Another situation is when threads cannot be used at all (e.g. because you plan to call Unix.fork later).

NOTE: this does not handle the Suspend effect, so await, fork-join, etc. will NOT work on this runner.

  • since 0.5
include module type of Runner
type task = unit -> unit
type t

A runner.

If a runner is no longer needed, shutdown can be used to signal all worker threads in it to stop (after they finish their work), and wait for them to stop.

The threads are distributed across a fixed domain pool (whose size is determined by Domain.recommended_domain_count on OCaml 5, and simple the single runtime on OCaml 4).

val size : t -> int

Number of threads/workers.

val num_tasks : t -> int

Current number of tasks. This is at best a snapshot, useful for metrics and debugging.

val shutdown : t -> unit

Shutdown the runner and wait for it to terminate. Idempotent.

val shutdown_without_waiting : t -> unit

Shutdown the pool, and do not wait for it to terminate. Idempotent.

exception Shutdown
val run_async : - ?name:string -> - ?ls:Task_local_storage.storage -> - t -> - task -> - unit

run_async pool f schedules f for later execution on the runner in one of the threads. f() will run on one of the runner's worker threads/domains.

  • parameter name

    if provided and Trace is present in dependencies, a span will be created when the task starts, and will stop when the task is over. (since NEXT_RELEASE)

  • parameter ls

    if provided, run the task with this initial local storage

  • raises Shutdown

    if the runner was shut down before run_async was called.

val run_wait_block : - ?name:string -> - ?ls:Task_local_storage.storage -> - t -> - (unit -> 'a) -> - 'a

run_wait_block pool f schedules f for later execution on the pool, like run_async. It then blocks the current thread until f() is done executing, and returns its result. If f() raises an exception, then run_wait_block pool f will raise it as well.

NOTE be careful with deadlocks (see notes in Fut.wait_block about the required discipline to avoid deadlocks).

  • raises Shutdown

    if the runner was already shut down

Implementing runners

module For_runner_implementors : sig ... end

This module is specifically intended for users who implement their own runners. Regular users of Moonpool should not need to look at it.

val get_current_runner : unit -> t option

Access the current runner. This returns Some r if the call happens on a thread that belongs in a runner.

  • since 0.5
val runner : t

The trivial runner that actually runs tasks at the calling point.

+Immediate_runner (moonpool.Moonpool.Immediate_runner)

Module Moonpool.Immediate_runner

Runner that runs tasks immediately in the caller thread.

Whenever a task is submitted to this runner via Runner.run_async r task, the task is run immediately in the caller thread as task(). There are no background threads, no resource, this is just a trivial implementation of the interface.

This can be useful when an implementation needs a runner, but there isn't enough work to justify starting an actual full thread pool.

Another situation is when threads cannot be used at all (e.g. because you plan to call Unix.fork later).

NOTE: this does not handle the Suspend effect, so await, fork-join, etc. will NOT work on this runner.

  • since 0.5
include module type of Runner
type task = unit -> unit
type t

A runner.

If a runner is no longer needed, shutdown can be used to signal all worker threads in it to stop (after they finish their work), and wait for them to stop.

The threads are distributed across a fixed domain pool (whose size is determined by Domain.recommended_domain_count on OCaml 5, and simple the single runtime on OCaml 4).

val size : t -> int

Number of threads/workers.

val num_tasks : t -> int

Current number of tasks. This is at best a snapshot, useful for metrics and debugging.

val shutdown : t -> unit

Shutdown the runner and wait for it to terminate. Idempotent.

val shutdown_without_waiting : t -> unit

Shutdown the pool, and do not wait for it to terminate. Idempotent.

exception Shutdown
val run_async : ?ls:Task_local_storage.storage -> t -> task -> unit

run_async pool f schedules f for later execution on the runner in one of the threads. f() will run on one of the runner's worker threads/domains.

  • parameter ls

    if provided, run the task with this initial local storage

  • raises Shutdown

    if the runner was shut down before run_async was called.

val run_wait_block : ?ls:Task_local_storage.storage -> t -> (unit -> 'a) -> 'a

run_wait_block pool f schedules f for later execution on the pool, like run_async. It then blocks the current thread until f() is done executing, and returns its result. If f() raises an exception, then run_wait_block pool f will raise it as well.

NOTE be careful with deadlocks (see notes in Fut.wait_block about the required discipline to avoid deadlocks).

  • raises Shutdown

    if the runner was already shut down

Implementing runners

module For_runner_implementors : sig ... end

This module is specifically intended for users who implement their own runners. Regular users of Moonpool should not need to look at it.

val get_current_runner : unit -> t option

Access the current runner. This returns Some r if the call happens on a thread that belongs in a runner.

  • since 0.5
val runner : t

The trivial runner that actually runs tasks at the calling point.

diff --git a/dev/moonpool/Moonpool/Runner/For_runner_implementors/index.html b/dev/moonpool/Moonpool/Runner/For_runner_implementors/index.html index 7e584aca..0f9c5247 100644 --- a/dev/moonpool/Moonpool/Runner/For_runner_implementors/index.html +++ b/dev/moonpool/Moonpool/Runner/For_runner_implementors/index.html @@ -3,6 +3,6 @@ size:(unit -> int) -> num_tasks:(unit -> int) -> shutdown:(wait:bool -> unit -> unit) -> - run_async:(name:string -> ls:Task_local_storage.storage -> task -> unit) -> + run_async:(ls:Task_local_storage.storage -> task -> unit) -> unit -> t

Create a new runner.

NOTE: the runner should support DLA and Suspend_ on OCaml 5.x, so that Fork_join and other 5.x features work properly.

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 get_current_runner to work.

diff --git a/dev/moonpool/Moonpool/Runner/index.html b/dev/moonpool/Moonpool/Runner/index.html index ac6e0122..07c5fc7b 100644 --- a/dev/moonpool/Moonpool/Runner/index.html +++ b/dev/moonpool/Moonpool/Runner/index.html @@ -1,12 +1,2 @@ -Runner (moonpool.Moonpool.Runner)

Module Moonpool.Runner

Interface for runners.

This provides an abstraction for running tasks in the background, which is implemented by various thread pools.

  • since 0.3
type task = unit -> unit
type t

A runner.

If a runner is no longer needed, shutdown can be used to signal all worker threads in it to stop (after they finish their work), and wait for them to stop.

The threads are distributed across a fixed domain pool (whose size is determined by Domain.recommended_domain_count on OCaml 5, and simple the single runtime on OCaml 4).

val size : t -> int

Number of threads/workers.

val num_tasks : t -> int

Current number of tasks. This is at best a snapshot, useful for metrics and debugging.

val shutdown : t -> unit

Shutdown the runner and wait for it to terminate. Idempotent.

val shutdown_without_waiting : t -> unit

Shutdown the pool, and do not wait for it to terminate. Idempotent.

exception Shutdown
val run_async : - ?name:string -> - ?ls:Task_local_storage.storage -> - t -> - task -> - unit

run_async pool f schedules f for later execution on the runner in one of the threads. f() will run on one of the runner's worker threads/domains.

  • parameter name

    if provided and Trace is present in dependencies, a span will be created when the task starts, and will stop when the task is over. (since NEXT_RELEASE)

  • parameter ls

    if provided, run the task with this initial local storage

  • raises Shutdown

    if the runner was shut down before run_async was called.

val run_wait_block : - ?name:string -> - ?ls:Task_local_storage.storage -> - t -> - (unit -> 'a) -> - 'a

run_wait_block pool f schedules f for later execution on the pool, like run_async. It then blocks the current thread until f() is done executing, and returns its result. If f() raises an exception, then run_wait_block pool f will raise it as well.

NOTE be careful with deadlocks (see notes in Fut.wait_block about the required discipline to avoid deadlocks).

  • raises Shutdown

    if the runner was already shut down

Implementing runners

module For_runner_implementors : sig ... end

This module is specifically intended for users who implement their own runners. Regular users of Moonpool should not need to look at it.

val get_current_runner : unit -> t option

Access the current runner. This returns Some r if the call happens on a thread that belongs in a runner.

  • since 0.5
+Runner (moonpool.Moonpool.Runner)

Module Moonpool.Runner

Interface for runners.

This provides an abstraction for running tasks in the background, which is implemented by various thread pools.

  • since 0.3
type task = unit -> unit
type t

A runner.

If a runner is no longer needed, shutdown can be used to signal all worker threads in it to stop (after they finish their work), and wait for them to stop.

The threads are distributed across a fixed domain pool (whose size is determined by Domain.recommended_domain_count on OCaml 5, and simple the single runtime on OCaml 4).

val size : t -> int

Number of threads/workers.

val num_tasks : t -> int

Current number of tasks. This is at best a snapshot, useful for metrics and debugging.

val shutdown : t -> unit

Shutdown the runner and wait for it to terminate. Idempotent.

val shutdown_without_waiting : t -> unit

Shutdown the pool, and do not wait for it to terminate. Idempotent.

exception Shutdown
val run_async : ?ls:Task_local_storage.storage -> t -> task -> unit

run_async pool f schedules f for later execution on the runner in one of the threads. f() will run on one of the runner's worker threads/domains.

  • parameter ls

    if provided, run the task with this initial local storage

  • raises Shutdown

    if the runner was shut down before run_async was called.

val run_wait_block : ?ls:Task_local_storage.storage -> t -> (unit -> 'a) -> 'a

run_wait_block pool f schedules f for later execution on the pool, like run_async. It then blocks the current thread until f() is done executing, and returns its result. If f() raises an exception, then run_wait_block pool f will raise it as well.

NOTE be careful with deadlocks (see notes in Fut.wait_block about the required discipline to avoid deadlocks).

  • raises Shutdown

    if the runner was already shut down

Implementing runners

module For_runner_implementors : sig ... end

This module is specifically intended for users who implement their own runners. Regular users of Moonpool should not need to look at it.

val get_current_runner : unit -> t option

Access the current runner. This returns Some r if the call happens on a thread that belongs in a runner.

  • since 0.5
diff --git a/dev/moonpool/Moonpool/Ws_pool/For_runner_implementors/index.html b/dev/moonpool/Moonpool/Ws_pool/For_runner_implementors/index.html index 98481d1f..6ed2b7b2 100644 --- a/dev/moonpool/Moonpool/Ws_pool/For_runner_implementors/index.html +++ b/dev/moonpool/Moonpool/Ws_pool/For_runner_implementors/index.html @@ -3,6 +3,6 @@ size:(unit -> int) -> num_tasks:(unit -> int) -> shutdown:(wait:bool -> unit -> unit) -> - run_async:(name:string -> ls:Task_local_storage.storage -> task -> unit) -> + run_async:(ls:Task_local_storage.storage -> task -> unit) -> unit -> t

Create a new runner.

NOTE: the runner should support DLA and Suspend_ on OCaml 5.x, so that Fork_join and other 5.x features work properly.

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 get_current_runner to work.

diff --git a/dev/moonpool/Moonpool/Ws_pool/index.html b/dev/moonpool/Moonpool/Ws_pool/index.html index 7a25a527..fea8b129 100644 --- a/dev/moonpool/Moonpool/Ws_pool/index.html +++ b/dev/moonpool/Moonpool/Ws_pool/index.html @@ -1,15 +1,5 @@ -Ws_pool (moonpool.Moonpool.Ws_pool)

Module Moonpool.Ws_pool

Work-stealing thread pool.

A pool of threads with a worker-stealing scheduler. The pool contains a fixed number of threads that wait for work items to come, process these, and loop.

This is good for CPU-intensive tasks that feature a lot of small tasks. Note that tasks will not always be processed in the order they are scheduled, so this is not great for workloads where the latency of individual tasks matter (for that see Fifo_pool).

This implements Runner.t since 0.3.

If a pool is no longer needed, shutdown can be used to signal all threads in it to stop (after they finish their work), and wait for them to stop.

The threads are distributed across a fixed domain pool (whose size is determined by Domain.recommended_domain_count on OCaml 5, and simply the single runtime on OCaml 4).

include module type of Runner
type task = unit -> unit
type t

A runner.

If a runner is no longer needed, shutdown can be used to signal all worker threads in it to stop (after they finish their work), and wait for them to stop.

The threads are distributed across a fixed domain pool (whose size is determined by Domain.recommended_domain_count on OCaml 5, and simple the single runtime on OCaml 4).

val size : t -> int

Number of threads/workers.

val num_tasks : t -> int

Current number of tasks. This is at best a snapshot, useful for metrics and debugging.

val shutdown : t -> unit

Shutdown the runner and wait for it to terminate. Idempotent.

val shutdown_without_waiting : t -> unit

Shutdown the pool, and do not wait for it to terminate. Idempotent.

exception Shutdown
val run_async : - ?name:string -> - ?ls:Task_local_storage.storage -> - t -> - task -> - unit

run_async pool f schedules f for later execution on the runner in one of the threads. f() will run on one of the runner's worker threads/domains.

  • parameter name

    if provided and Trace is present in dependencies, a span will be created when the task starts, and will stop when the task is over. (since NEXT_RELEASE)

  • parameter ls

    if provided, run the task with this initial local storage

  • raises Shutdown

    if the runner was shut down before run_async was called.

val run_wait_block : - ?name:string -> - ?ls:Task_local_storage.storage -> - t -> - (unit -> 'a) -> - 'a

run_wait_block pool f schedules f for later execution on the pool, like run_async. It then blocks the current thread until f() is done executing, and returns its result. If f() raises an exception, then run_wait_block pool f will raise it as well.

NOTE be careful with deadlocks (see notes in Fut.wait_block about the required discipline to avoid deadlocks).

  • raises Shutdown

    if the runner was already shut down

Implementing runners

module For_runner_implementors : sig ... end

This module is specifically intended for users who implement their own runners. Regular users of Moonpool should not need to look at it.

val get_current_runner : unit -> t option

Access the current runner. This returns Some r if the call happens on a thread that belongs in a runner.

  • since 0.5
type ('a, 'b) create_args = +Ws_pool (moonpool.Moonpool.Ws_pool)

Module Moonpool.Ws_pool

Work-stealing thread pool.

A pool of threads with a worker-stealing scheduler. The pool contains a fixed number of threads that wait for work items to come, process these, and loop.

This is good for CPU-intensive tasks that feature a lot of small tasks. Note that tasks will not always be processed in the order they are scheduled, so this is not great for workloads where the latency of individual tasks matter (for that see Fifo_pool).

This implements Runner.t since 0.3.

If a pool is no longer needed, shutdown can be used to signal all threads in it to stop (after they finish their work), and wait for them to stop.

The threads are distributed across a fixed domain pool (whose size is determined by Domain.recommended_domain_count on OCaml 5, and simply the single runtime on OCaml 4).

include module type of Runner
type task = unit -> unit
type t

A runner.

If a runner is no longer needed, shutdown can be used to signal all worker threads in it to stop (after they finish their work), and wait for them to stop.

The threads are distributed across a fixed domain pool (whose size is determined by Domain.recommended_domain_count on OCaml 5, and simple the single runtime on OCaml 4).

val size : t -> int

Number of threads/workers.

val num_tasks : t -> int

Current number of tasks. This is at best a snapshot, useful for metrics and debugging.

val shutdown : t -> unit

Shutdown the runner and wait for it to terminate. Idempotent.

val shutdown_without_waiting : t -> unit

Shutdown the pool, and do not wait for it to terminate. Idempotent.

exception Shutdown
val run_async : ?ls:Task_local_storage.storage -> t -> task -> unit

run_async pool f schedules f for later execution on the runner in one of the threads. f() will run on one of the runner's worker threads/domains.

  • parameter ls

    if provided, run the task with this initial local storage

  • raises Shutdown

    if the runner was shut down before run_async was called.

val run_wait_block : ?ls:Task_local_storage.storage -> t -> (unit -> 'a) -> 'a

run_wait_block pool f schedules f for later execution on the pool, like run_async. It then blocks the current thread until f() is done executing, and returns its result. If f() raises an exception, then run_wait_block pool f will raise it as well.

NOTE be careful with deadlocks (see notes in Fut.wait_block about the required discipline to avoid deadlocks).

  • raises Shutdown

    if the runner was already shut down

Implementing runners

module For_runner_implementors : sig ... end

This module is specifically intended for users who implement their own runners. Regular users of Moonpool should not need to look at it.

val get_current_runner : unit -> t option

Access the current runner. This returns Some r if the call happens on a thread that belongs in a runner.

  • since 0.5
type ('a, 'b) create_args = ?on_init_thread:(dom_id:int -> t_id:int -> unit -> unit) -> ?on_exit_thread:(dom_id:int -> t_id:int -> unit -> unit) -> ?on_exn:(exn -> Stdlib.Printexc.raw_backtrace -> unit) -> diff --git a/dev/moonpool/Moonpool/index.html b/dev/moonpool/Moonpool/index.html index 0b3915b8..da3c5fea 100644 --- a/dev/moonpool/Moonpool/index.html +++ b/dev/moonpool/Moonpool/index.html @@ -1,21 +1,17 @@ Moonpool (moonpool.Moonpool)

Module Moonpool

Moonpool

A pool within a bigger pool (ie the ocean). Here, we're talking about pools of Thread.t that are dispatched over several Domain.t to enable parallelism.

We provide several implementations of pools with distinct scheduling strategies, alongside some concurrency primitives such as guarding locks (Lock.t) and futures (Fut.t).

module Ws_pool : sig ... end

Work-stealing thread pool.

module Fifo_pool : sig ... end

A simple thread pool in FIFO order.

module Runner : sig ... end

Interface for runners.

module Immediate_runner : sig ... end

Runner that runs tasks immediately in the caller thread.

module Exn_bt : sig ... end

Exception with backtrace.

exception Shutdown

Exception raised when trying to run tasks on runners that have been shut down.

  • since NEXT_RELEASE
val start_thread_on_some_domain : ('a -> unit) -> 'a -> Thread.t

Similar to Thread.create, but it picks a background domain at random to run the thread. This ensures that we don't always pick the same domain to run all the various threads needed in an application (timers, event loops, etc.)

val run_async : - ?name:string -> ?ls:Task_local_storage.storage -> Runner.t -> (unit -> unit) -> - unit

run_async runner task schedules the task to run on the given runner. This means task() will be executed at some point in the future, possibly in another thread.

  • parameter name

    if provided and Trace is present in dependencies, a span will be created when the task starts, and will stop when the task is over. (since NEXT_RELEASE)

  • since 0.5
val run_wait_block : - ?name:string -> + unit

run_async runner task schedules the task to run on the given runner. This means task() will be executed at some point in the future, possibly in another thread.

  • since 0.5
val run_wait_block : ?ls:Task_local_storage.storage -> Runner.t -> (unit -> 'a) -> 'a

run_wait_block runner f schedules f for later execution on the runner, like run_async. It then blocks the current thread until f() is done executing, and returns its result. If f() raises an exception, then run_wait_block pool f will raise it as well.

NOTE be careful with deadlocks (see notes in Fut.wait_block about the required discipline to avoid deadlocks).

  • raises Shutdown

    if the runner was already shut down

  • since NEXT_RELEASE

Number of threads recommended to saturate the CPU. For IO pools this makes little sense (you might want more threads than this because many of them will be blocked most of the time).

  • since 0.5
val spawn : - ?name:string -> ?ls:Task_local_storage.storage -> on:Runner.t -> (unit -> 'a) -> - 'a Fut.t

spawn ~on f runs f() on the runner (a thread pool typically) and returns a future result for it. See Fut.spawn.

  • parameter name

    if provided and Trace is present in dependencies, a span will be created for the future. (since 0.6)

  • since 0.5
val spawn_on_current_runner : - ?name:string -> + 'a Fut.t

spawn ~on f runs f() on the runner (a thread pool typically) and returns a future result for it. See Fut.spawn.

  • since 0.5
val spawn_on_current_runner : ?ls:Task_local_storage.storage -> (unit -> 'a) -> - 'a Fut.t

See Fut.spawn_on_current_runner.

  • parameter name

    see spawn. since 0.6.

  • since 0.5
val await : 'a Fut.t -> 'a

Await a future. See await. Only on OCaml >= 5.0.

  • since 0.5
module Lock : sig ... end

Mutex-protected resource.

module Fut : sig ... end

Futures.

module Chan : sig ... end

Channels.

module Task_local_storage : sig ... end

Task-local storage.

module Thread_local_storage = Moonpool_private.Thread_local_storage_
module Blocking_queue : sig ... end

A simple blocking queue.

module Bounded_queue : sig ... end

A blocking queue of finite size.

module Atomic = Moonpool_private.Atomic_

Atomic values.

+ 'a Fut.t
val await : 'a Fut.t -> 'a

Await a future. See await. Only on OCaml >= 5.0.

  • since 0.5
module Lock : sig ... end

Mutex-protected resource.

module Fut : sig ... end

Futures.

module Chan : sig ... end

Channels.

module Task_local_storage : sig ... end

Task-local storage.

module Thread_local_storage = Moonpool_private.Thread_local_storage_
module Blocking_queue : sig ... end

A simple blocking queue.

module Bounded_queue : sig ... end

A blocking queue of finite size.

module Atomic = Moonpool_private.Atomic_

Atomic values.

diff --git a/dev/moonpool/Moonpool_fib/Fiber/index.html b/dev/moonpool/Moonpool_fib/Fiber/index.html index 22e96129..61f1d80c 100644 --- a/dev/moonpool/Moonpool_fib/Fiber/index.html +++ b/dev/moonpool/Moonpool_fib/Fiber/index.html @@ -1,2 +1,2 @@ -Fiber (moonpool.Moonpool_fib.Fiber)

Module Moonpool_fib.Fiber

Fibers.

A fiber is a lightweight computation that runs cooperatively alongside other fibers. In the context of moonpool, fibers have additional properties:

  • they run in a moonpool runner
  • they form a simple supervision tree, enabling a limited form of structured concurrency
type 'a t

A fiber returning a value of type 'a.

val res : 'a t -> 'a Moonpool.Fut.t

Future result of the fiber.

type 'a callback = 'a Moonpool.Exn_bt.result -> unit

Callbacks that are called when a fiber is done.

type cancel_callback = Moonpool.Exn_bt.t -> unit
val peek : 'a t -> 'a Moonpool.Fut.or_error option

Peek inside the future result

val is_done : _ t -> bool

Has the fiber completed?

val is_cancelled : _ t -> bool

Has the fiber completed with a failure?

val is_success : _ t -> bool

Has the fiber completed with a value?

val await : 'a t -> 'a

await fib is like Fut.await (res fib)

val check_if_cancelled : unit -> unit

Check if the current fiber is cancelled, in which case this raises. Must be run from inside a fiber.

  • raises Failure

    if not.

val yield : unit -> unit

Yield control to the scheduler from the current fiber.

  • raises Failure

    if not run from inside a fiber.

val with_cancel_callback : _ t -> cancel_callback -> (unit -> 'a) -> 'a

with_cancel_callback fib cb (fun () -> <e>) evaluates e in a scope in which, if the fiber fib is cancelled, cb() is called. If e returns without the fiber being cancelled, this callback is removed.

val on_result : 'a t -> 'a callback -> unit

Wait for fiber to be done and call the callback with the result. If the fiber is done already then the callback is invoked immediately with its result.

val spawn_top : ?name:string -> on:Moonpool.Runner.t -> (unit -> 'a) -> 'a t

spawn_top ~on f spawns a new (toplevel) fiber onto the given runner. This fiber is not the child of any other fiber: its lifetime is only determined by the lifetime of f().

spawn_link ~protect f spawns a sub-fiber f_child from a running fiber parent. The sub-fiber f_child is attached to the current fiber and fails if the current fiber parent fails.

  • parameter protect

    if true, when f_child fails, it does not affect parent. If false, f_child failing also causes parent to fail (and therefore all other children of parent).

    Must be run from inside a fiber.

  • raises Failure

    if not run from inside a fiber.

+Fiber (moonpool.Moonpool_fib.Fiber)

Module Moonpool_fib.Fiber

Fibers.

A fiber is a lightweight computation that runs cooperatively alongside other fibers. In the context of moonpool, fibers have additional properties:

  • they run in a moonpool runner
  • they form a simple supervision tree, enabling a limited form of structured concurrency
type 'a t

A fiber returning a value of type 'a.

val res : 'a t -> 'a Moonpool.Fut.t

Future result of the fiber.

type 'a callback = 'a Moonpool.Exn_bt.result -> unit

Callbacks that are called when a fiber is done.

type cancel_callback = Moonpool.Exn_bt.t -> unit
val peek : 'a t -> 'a Moonpool.Fut.or_error option

Peek inside the future result

val is_done : _ t -> bool

Has the fiber completed?

val is_cancelled : _ t -> bool

Has the fiber completed with a failure?

val is_success : _ t -> bool

Has the fiber completed with a value?

val await : 'a t -> 'a

await fib is like Fut.await (res fib)

val check_if_cancelled : unit -> unit

Check if the current fiber is cancelled, in which case this raises. Must be run from inside a fiber.

  • raises Failure

    if not.

val yield : unit -> unit

Yield control to the scheduler from the current fiber.

  • raises Failure

    if not run from inside a fiber.

val with_cancel_callback : _ t -> cancel_callback -> (unit -> 'a) -> 'a

with_cancel_callback fib cb (fun () -> <e>) evaluates e in a scope in which, if the fiber fib is cancelled, cb() is called. If e returns without the fiber being cancelled, this callback is removed.

val on_result : 'a t -> 'a callback -> unit

Wait for fiber to be done and call the callback with the result. If the fiber is done already then the callback is invoked immediately with its result.

val spawn_top : on:Moonpool.Runner.t -> (unit -> 'a) -> 'a t

spawn_top ~on f spawns a new (toplevel) fiber onto the given runner. This fiber is not the child of any other fiber: its lifetime is only determined by the lifetime of f().

spawn_link ~protect f spawns a sub-fiber f_child from a running fiber parent. The sub-fiber f_child is attached to the current fiber and fails if the current fiber parent fails.

  • parameter protect

    if true, when f_child fails, it does not affect parent. If false, f_child failing also causes parent to fail (and therefore all other children of parent).

    Must be run from inside a fiber.

  • raises Failure

    if not run from inside a fiber.

diff --git a/dev/moonpool/Moonpool_private/Tracing_/index.html b/dev/moonpool/Moonpool_private/Tracing_/index.html index fba00eda..0dc5c363 100644 --- a/dev/moonpool/Moonpool_private/Tracing_/index.html +++ b/dev/moonpool/Moonpool_private/Tracing_/index.html @@ -1,2 +1,2 @@ -Tracing_ (moonpool.Moonpool_private.Tracing_)

Module Moonpool_private.Tracing_

val dummy_span : int64
val enter_span : string -> int64
val exit_span : int64 -> unit
val enabled : unit -> bool
val set_thread_name : string -> unit
+Tracing_ (moonpool.Moonpool_private.Tracing_)

Module Moonpool_private.Tracing_

val dummy_span : int64
val enter_span : string -> int64
val exit_span : int64 -> unit
val with_span : string -> (int64 -> 'a) -> 'a
val enabled : unit -> bool
val set_thread_name : string -> unit