+# Lwt.state p;;
+- : '_a Lwt.state = Lwt.Sleep
+# push 42;;
+- : unit = ()
+# Lwt.state p;;
+- : int Lwt.state = Lwt.Return 42
+]}
+
+ Another interesting feature is the ability to limit events
+ (resp. signals) from occurring (resp. changing) too often. For example,
+ suppose you are doing a program which displays something on the screen
+ each time a signal changes. If at some point the signal changes 1000
+ times per second, you probably don't want to render it 1000 times per
+ second. For that you use [Lwt_react.S.limit]:
+
+{[
+val limit : (unit -> unit Lwt.t) -> 'a React.signal -> 'a React.signal
+]}
+
+ [Lwt_react.S.limit f signal] returns a signal which varies as
+ [signal] except that two consecutive updates are separated by a
+ call to [f]. For example if [f] returns a promise which is pending
+ for 0.1 seconds, then there will be no more than 10 changes per
+ second:
+
+{[
+open Lwt_react
+
+let draw x =
+ (* Draw the screen *)
+ …
+
+let () =
+ (* The signal we are interested in: *)
+ let signal = … in
+
+ (* The limited signal: *)
+ let signal' = S.limit (fun () -> Lwt_unix.sleep 0.1) signal in
+
+ (* Redraw the screen each time the limited signal change: *)
+ S.notify_p draw signal'
+]}
+
+{1 Other libraries }
+
+{2 Parallelise computations to other cores }
+
+ If you have some compute-intensive steps within your program, you can execute
+ them on a separate core. You can get performance benefits from the
+ parallelisation. In addition, whilst your compute-intensive function is running
+ on a different core, your normal I/O-bound tasks continue running on the
+ original core.
+
+ The module {!Lwt_domain} from the [lwt_domain] package provides all the
+ necessary helpers to achieve this. It is based on the [Domainslib] library
+ and uses similar concepts (such as tasks and pools).
+
+ First, you need to create a task pool:
+
+{[
+val setup_pool : ?name:string -> int -> pool
+]}
+
+ Then you simple detach the function calls to the created pool:
+
+{[
+val detach : pool -> ('a -> 'b) -> 'a -> 'b Lwt.t
+]}
+
+ The returned promise resolves as soon as the function returns.
+
+{2 Detaching computation to preemptive threads }
+
+ It may happen that you want to run a function which will take time to
+ compute or that you want to use a blocking function that cannot be
+ used in a non-blocking way. For these situations, [Lwt] allows you to
+ {e detach} the computation to a preemptive thread.
+
+ This is done by the module [Lwt_preemptive] of the
+ [lwt.unix] package which maintains a pool of system
+ threads. The main function is:
+
+{[
+val detach : ('a -> 'b) -> 'a -> 'b Lwt.t
+]}
+
+ [detach f x] will execute [f x] in another thread and
+ return a pending promise, usable from the main thread, which will be fulfilled
+ with the result of the preemptive thread.
+
+ If you want to trigger some [Lwt] operations from your detached thread,
+ you have to call back into the main thread using
+ [Lwt_preemptive.run_in_main]:
+
+{[
+val run_in_main : (unit -> 'a Lwt.t) -> 'a
+]}
+
+ This is roughly the equivalent of [Lwt.main_run], but for detached
+ threads, rather than for the whole process. Note that you must not call
+ [Lwt_main.run] in a detached thread.
+
+{2 SSL support }
+
+ The library [Lwt_ssl] allows use of SSL asynchronously.
+
+{1 Writing stubs using [Lwt] }
+
+{2 Thread-safe notifications }
+
+ If you want to notify the main thread from another thread, you can use the [Lwt]
+ thread safe notification system. First you need to create a notification identifier
+ (which is just an integer) from the OCaml side using the
+ [Lwt_unix.make_notification] function, then you can send it from either the
+ OCaml code with [Lwt_unix.send_notification] function, or from the C code using
+ the function [lwt_unix_send_notification] (defined in [lwt_unix_.h]).
+
+ Notifications are received and processed asynchronously by the main thread.
+
+{2 Jobs }
+
+ For operations that cannot be executed asynchronously, [Lwt]
+ uses a system of jobs that can be executed in a different threads. A
+ job is composed of three functions:
+
+{ul
+ {- A stub function to create the job. It must allocate a new job
+ structure and fill its [worker] and [result] fields. This
+ function is executed in the main thread.
+ The return type for the OCaml external must be of the form ['a job].}
+ {- A function which executes the job. This one may be executed asynchronously
+ in another thread. This function must not:
+ {ul
+ {- access or allocate OCaml block values (tuples, strings, …),}
+ {- call OCaml code.}}}
+ {- A function which reads the result of the job, frees resources and
+ returns the result as an OCaml value. This function is executed in
+ the main thread.}}
+
+ With [Lwt < 2.3.3], 4 functions (including 3 stubs) were
+ required. It is still possible to use this mode but it is
+ deprecated.
+
+ We show as example the implementation of [Lwt_unix.mkdir]. On the C
+ side we have:
+
+{@c[/**/
+/* Structure holding informations for calling [mkdir]. */
+struct job_mkdir {
+ /* Informations used by lwt.
+ It must be the first field of the structure. */
+ struct lwt_unix_job job;
+ /* This field store the result of the call. */
+ int result;
+ /* This field store the value of [errno] after the call. */
+ int errno_copy;
+ /* Pointer to a copy of the path parameter. */
+ char* path;
+ /* Copy of the mode parameter. */
+ int mode;
+ /* Buffer for storing the path. */
+ char data[];
+};
+
+/* The function calling [mkdir]. */
+static void worker_mkdir(struct job_mkdir* job)
+{
+ /* Perform the blocking call. */
+ job->result = mkdir(job->path, job->mode);
+ /* Save the value of errno. */
+ job->errno_copy = errno;
+}
+
+/* The function building the caml result. */
+static value result_mkdir(struct job_mkdir* job)
+{
+ /* Check for errors. */
+ if (job->result < 0) {
+ /* Save the value of errno so we can use it
+ once the job has been freed. */
+ int error = job->errno_copy;
+ /* Copy the contents of job->path into a caml string. */
+ value string_argument = caml_copy_string(job->path);
+ /* Free the job structure. */
+ lwt_unix_free_job(&job->job);
+ /* Raise the error. */
+ unix_error(error, "mkdir", string_argument);
+ }
+ /* Free the job structure. */
+ lwt_unix_free_job(&job->job);
+ /* Return the result. */
+ return Val_unit;
+}
+
+/* The stub creating the job structure. */
+CAMLprim value lwt_unix_mkdir_job(value path, value mode)
+{
+ /* Get the length of the path parameter. */
+ mlsize_t len_path = caml_string_length(path) + 1;
+ /* Allocate a new job. */
+ struct job_mkdir* job =
+ (struct job_mkdir*)lwt_unix_new_plus(struct job_mkdir, len_path);
+ /* Set the offset of the path parameter inside the job structure. */
+ job->path = job->data;
+ /* Copy the path parameter inside the job structure. */
+ memcpy(job->path, String_val(path), len_path);
+ /* Initialize function fields. */
+ job->job.worker = (lwt_unix_job_worker)worker_mkdir;
+ job->job.result = (lwt_unix_job_result)result_mkdir;
+ /* Copy the mode parameter. */
+ job->mode = Int_val(mode);
+ /* Wrap the structure into a caml value. */
+ return lwt_unix_alloc_job(&job->job);
+}
+]}
+
+ and on the ocaml side:
+
+{[
+(* The stub for creating the job. *)
+external mkdir_job : string -> int -> unit job = "lwt_unix_mkdir_job"
+
+(* The ocaml function. *)
+let mkdir name perms = Lwt_unix.run_job (mkdir_job name perms)
+]}
diff --git a/lwt/index.html b/lwt/index.html
index 624d4d44..c1f99bfd 100644
--- a/lwt/index.html
+++ b/lwt/index.html
@@ -22,4 +22,4 @@ let () =
| 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
- 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
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 | |