diff --git a/dev/lwt/Lwt/index.html b/dev/lwt/Lwt/index.html index c3795c40..9910e9cd 100644 --- a/dev/lwt/Lwt/index.html +++ b/dev/lwt/Lwt/index.html @@ -194,7 +194,7 @@ let () = 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:
Lwt.bind, Lwt.catch, Lwt.join, etc., are top-level promises.Lwt_main.run, as can be seen in most examples in this manual.Lwt.async.val async_exception_hook : (exn -> unit) refReference 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 -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:
Lwt.bind, Lwt.catch, Lwt.join, etc., are top-level promises.Lwt_main.run, as can be seen in most examples in this manual.Lwt.async.val async_exception_hook : (exn -> unit) Stdlib.refReference 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.
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 =
@@ -281,7 +281,7 @@ let () =
(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_stringThe 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.p_1 becomes rejected, p_3 is rejected with the same exception.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.f v returns another value v', p_3 is fulfilled with v'.f v raises exception exn, p_3 is rejected with exn.val on_success : 'a t -> ('a -> unit) -> unitLwt.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) -> unitLwt.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) -> unitLwt.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) -> unitLwt.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.
module Infix : sig ... endThis module provides several infix operators for making programming with Lwt more convenient.
module Let_syntax : sig ... endmodule Syntax : sig ... endval return_unit : unit tLwt.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 tLwt.return_none is like Lwt.return_unit, but for Lwt.return None.
val return_nil : _ list tLwt.return_nil is like Lwt.return_unit, but for Lwt.return [].
val return_true : bool tLwt.return_true is like Lwt.return_unit, but for Lwt.return true.
val return_false : bool tLwt.return_false is like Lwt.return_unit, but for Lwt.return false.
val return_some : 'a -> 'a option tCounterpart 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.
Like Lwt.return_some, this function performs no optimization.
Like Lwt.return_some, this function performs no optimization.
val fail_with : string -> _ tLwt.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 -> _ tLwt.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.
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.
Lwt.of_result r converts an r to a resolved promise.
r is Ok v, Lwt.of_result r is Lwt.return v, i.e. a promise fulfilled with v.r is Error exn, Lwt.of_result r is Lwt.fail exn, i.e. a promise rejected with exn.Lwt.wakeup_later_result r result resolves the pending promise p associated to resolver r, according to result:
result is Ok v, p is fulfilled with v.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.
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.
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 keyCreates 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 optionRetrieves the value currently associated with the given implicit callback argument key.
See Lwt.with_value.
val with_value : 'a key -> 'a option -> (unit -> 'b) -> 'bLwt.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 () =
+ Lwt_io.(read_line stdin) >|= int_of_stringThe 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.p_1 becomes rejected, p_3 is rejected with the same exception.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.f v returns another value v', p_3 is fulfilled with v'.f v raises exception exn, p_3 is rejected with exn.val on_success : 'a t -> ('a -> unit) -> unitLwt.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) -> unitLwt.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) -> unitLwt.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) -> unitLwt.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.
module Infix : sig ... endThis module provides several infix operators for making programming with Lwt more convenient.
module Let_syntax : sig ... endmodule Syntax : sig ... endval return_unit : unit tLwt.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 tLwt.return_none is like Lwt.return_unit, but for Lwt.return None.
val return_nil : _ list tLwt.return_nil is like Lwt.return_unit, but for Lwt.return [].
val return_true : bool tLwt.return_true is like Lwt.return_unit, but for Lwt.return true.
val return_false : bool tLwt.return_false is like Lwt.return_unit, but for Lwt.return false.
val return_some : 'a -> 'a option tCounterpart 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, _) Stdlib.result tLike Lwt.return_some, this function performs no optimization.
val return_error : 'e -> (_, 'e) Stdlib.result tLike Lwt.return_some, this function performs no optimization.
val fail_with : string -> _ tLwt.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 -> _ tLwt.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.
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) Stdlib.result -> 'a tLwt.of_result r converts an r to a resolved promise.
r is Ok v, Lwt.of_result r is Lwt.return v, i.e. a promise fulfilled with v.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) Stdlib.result -> unitLwt.wakeup_later_result r result resolves the pending promise p associated to resolver r, according to result:
result is Ok v, p is fulfilled with v.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.
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.
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 keyCreates 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 optionRetrieves the value currently associated with the given implicit callback argument key.
See Lwt.with_value.
val with_value : 'a key -> 'a option -> (unit -> 'b) -> 'bLwt.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 () =
@@ -298,7 +298,7 @@ let read_int : unit -> int Lwt.t = fun () ->
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.Lwt.bind.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.sleep promise will be resolved.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.sleep I/O completes, resolving the sleep promise.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!".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.
val wakeup : 'a u -> 'a -> unitLwt.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 -> unitLwt.wakeup_exn r exn is like Lwt.wakeup_later_exn r exn, but has the same problems as Lwt.wakeup.
Lwt.wakeup_result r result is like Lwt.wakeup_later_result r result, but has the same problems as Lwt.wakeup.
val add_task_r : 'a u Lwt_sequence.t -> 'a tLwt.add_task_r sequence is equivalent to
let p, r = Lwt.task () in
+(* 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.Lwt.bind.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.sleep promise will be resolved.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.sleep I/O completes, resolving the sleep promise.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!".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.
val wakeup : 'a u -> 'a -> unitLwt.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 -> unitLwt.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) Stdlib.result -> unitLwt.wakeup_result r result is like Lwt.wakeup_later_result r result, but has the same problems as Lwt.wakeup.
val add_task_r : 'a u Lwt_sequence.t -> 'a tLwt.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);
pval add_task_l : 'a u Lwt_sequence.t -> 'a tLike Lwt.add_task_r, but the equivalent code calls Lwt_sequence.add_l instead.
val pause : unit -> unit tLwt.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 () =
diff --git a/dev/lwt/Lwt_result/index.html b/dev/lwt/Lwt_result/index.html
index d8248cde..074fd4ac 100644
--- a/dev/lwt/Lwt_result/index.html
+++ b/dev/lwt/Lwt_result/index.html
@@ -1,2 +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.
val return : 'a -> ('a, _) tval fail : 'b -> (_, 'b) tcatch x behaves like return y if x () evaluates to y, and like fail e if x () raises e
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.
iter f r is f v if r is a promise resolved with Ok v, and Lwt.return_unit otherwise.
iter_error f r is f v if r is a promise resolved with Error v, and Lwt.return_unit otherwise.
module Infix : sig ... endmodule Let_syntax : sig ... endmodule Syntax : sig ... endDeprecated
+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) Stdlib.result Lwt.tval return : 'a -> ('a, _) tval fail : 'b -> (_, 'b) tval lift : ('a, 'b) Stdlib.result -> ('a, 'b) tcatch x behaves like return y if x () evaluates to y, and like fail e if x () raises e
val bind_result : ('a, 'e) t -> ('a -> ('b, 'e) Stdlib.result) -> ('b, 'e) tLwt.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.
iter f r is f v if r is a promise resolved with Ok v, and Lwt.return_unit otherwise.
iter_error f r is f v if r is a promise resolved with Error v, and Lwt.return_unit otherwise.
module Infix : sig ... endmodule Let_syntax : sig ... endmodule Syntax : sig ... endDeprecated
diff --git a/dev/moonpool/Moonpool/Background_thread/For_runner_implementors/index.html b/dev/moonpool/Moonpool/Background_thread/For_runner_implementors/index.html
index 681bb222..3a8c3d19 100644
--- a/dev/moonpool/Moonpool/Background_thread/For_runner_implementors/index.html
+++ b/dev/moonpool/Moonpool/Background_thread/For_runner_implementors/index.html
@@ -5,4 +5,5 @@
shutdown:(wait:bool -> unit -> unit) ->
run_async:(ls:Task_local_storage.storage -> task -> unit) ->
unit ->
- tCreate 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.
val k_cur_runner : t option ref Moonpool_private.Thread_local_storage_.keyKey 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.