Lwt manual

Introduction

When writing a program, a common developer's task is to handle IO
operations. Indeed most software interact with several different
resources, such as:

the kernel, by doing system calls

the user, by reading the keyboard, the mouse, or any input device

a graphical server, to build graphical user interface

other computers, by using the network

...

When this list contains only one item, it is pretty easy to
handle. However as this list grows it becomes harder and harder to
make everything works together. Several choices have been proposed
to solve this problem:

using a main loop, and integrate all components we are
interacting with into this main loop.

using preemptive system threads

Both solutions have their advantages and their drawbacks. For the
first one, it may work, but it becomes very complicated to write
a piece of asynchronous sequential code. The typical example is
graphical user interfaces freezing and not redrawing themselves
because they are waiting for some blocking part of the code to
complete.

If you already wrote code using preemptive threads, you should know
that doing it right with threads is a hard job. Moreover system
threads consume non negligible resources, and so you can only launch
a limited number of threads at the same time. Thus this is not a
real solution.

Lwt offers a new alternative. It provides very light-weight
cooperative threads; ``launching'' a thread is a very fast
operation, it does not require a new stack, a new process, or
anything else. Moreover context switches are very fast. In fact, it
is so easy that we will launch a thread for every system call. And
composing cooperative threads will allow us to write highly
asynchronous programs.

In a first part, we will explain the concepts of Lwt, then we will
describe the many sub-libraries of Lwt.

The Lwt core library

In this section we describe the basics of Lwt. It is advised to
start an ocaml toplevel and try the given code examples. To start,
launch ocaml in a terminal or in emacs with the tuareg
mode, and type:

# #use "topfind";;
# #require "lwt.simple-top";;

lwt.simple-top makes sure Lwt threads can run while
using the toplevel. You do not need it if you are using utop.

Lwt concepts

Let's take a classical function of the Pervasives module:

#Pervasives.input_char;;-:in_channel->char=<fun>

This function will wait for a character to come on the given input
channel, and then return it. The problem with this function is that it is
blocking: while it is being executed, the whole program will be
blocked, and other events will not be handled until it returns.

Now let's look at the lwt equivalent:

#Lwt_io.read_char;;-:Lwt_io.input_channel->charLwt.t=<fun>

As you can see, it does not return a character but something of
type char Lwt.t. The type 'a Lwt.t is the type
of threads returning a value of type 'a. Actually the
Lwt_io.read_char will try to read a character from the
given input channel and immediately returns a light-weight
thread.

Now, let's see what we can do with a Lwt thread. The following
code creates a pipe, and launches a thread reading on the input side:

Primitives for thread composition

The most important operation you need to know is bind:

valbind:'aLwt.t->('a->'bLwt.t)->'bLwt.t

bind t f creates a thread which waits for t to
terminate, then passes the result to f. If t is a
sleeping thread, then bind t f will be a sleeping thread too,
until t terminates. If t fails, then the resulting
thread will fail with the same exception. For example, consider the
following expression:

This code will first wait for the user to enter a line of text, then
print a message on the standard output.

Similarly to bind, there is a function to handle the case
when t fails:

valcatch:(unit->'aLwt.t)->(exn->'aLwt.t)->'aLwt.t

catch f g will call f (), then waits for its
termination, and if it fails with an exception exn, calls
g exn to handle it. Note that both exceptions raised with
Pervasives.raise and Lwt.fail are caught by
catch.

Cancelable threads

In some case, we may want to cancel a thread. For example, because it
has not terminated after a timeout. This can be done with cancelable
threads. To create a cancelable thread, you must use the
Lwt.task function:

valtask:unit->'aLwt.t*'aLwt.u

It has the same semantics as Lwt.wait except that the
sleeping thread can be canceled with Lwt.cancel:

valcancel:'aLwt.t->unit

The thread will then fail with the exception
Lwt.Canceled. To execute a function when the thread is
canceled, you must use Lwt.on_cancel:

valon_cancel:'aLwt.t->(unit->unit)->unit

Note that it is also possible to cancel a thread which has not been
created with Lwt.task. In this case, the deepest cancelable
thread connected with the given thread will be cancelled.

The last one, pick, is the same as choice except that it cancels
all other threads when one terminates.

Threads local storage

Lwt can store variables with different values on different
threads. This is called threads local storage. For example, this can
be used to store contexts or thread identifiers. The contents of a
variable can be read with:

valLwt.get:'aLwt.key->'aoption

which takes a key to identify the variable we want to read and
returns either None if the variable is not set, or
Some x if it is. The value returned is the value of the
variable in the current thread.

New keys can be created with:

valLwt.new_key:unit->'aLwt.key

To set a variable, you must use:

valLwt.with_value:'aLwt.key->'aoption->(unit->'b)->'b

with_value key value f will execute f with
the binding key -> value. The old value associated to
key is restored after f terminates.

For example, you can use local storage to store thread identifiers
and use them in logs:

Rules

Lwt will always try to execute as much as possible before yielding and
switching to another cooperative thread. In order to make it work well,
you must follow the following rules:

do not write functions that may take time to complete without
using Lwt,

do not do IOs that may block, otherwise the whole program will
hang. You must instead use asynchronous IOs operations.

The syntax extension

Lwt offers a syntax extension which increases code readability and
makes coding using Lwt easier. To use it add the lwt.syntax package when
compiling:

$ocamlfindocamlc-syntaxcamlp4o-packagelwt.syntax-linkpkg-ofoofoo.ml

Or in the toplevel (after loading topfind):

##camlp4o;;##require"lwt.syntax";;

The following constructions are added to the language:

lwtpattern1=expr1 [ andpattern2=expr2 ... ] inexpr
which is a parallel let-binding construction. For example in the
following code:

lwtx=f()andy=g()inexpr

the thread f () and g () are launched concurrently
and their results are then bound to x and y in the
expression expr.

Of course you can also launch the two threads sequentially by
writing your code like that:

lwtx=f()inlwty=g()inexpr

try_lwtexpr [ withpattern1->expr1 ... ] [ finallyexpr' ]
which is the equivalent of the standard try-with
construction but for Lwt. Both exceptions raised by
Pervasives.raise and Lwt.fail are caught.

for_lwtident=exprinit ( to|downto ) exprfinaldoexprdone
which is the equivalent of the standard for construction
but for Lwt.

raise_lwtexn
which is the same as Lwt.failexn but with backtrace support.

Correspondence table

You might appreciate the following table to write code using lwt:

without Lwt

with Lwt

letpattern1=expr1

lwtpattern1=expr1

andpattern2=expr2

andpattern2=expr2

...

...

andpatternn=exprnin

andpatternn=exprnin

expr

expr

try

try_lwt

expr

expr

with

with

|pattern1->expr1

|pattern1->expr1

|pattern2->expr2

|pattern2->expr2

...

...

|patternn->exprn

|patternn->exprn

forident=exprinittoexprfinaldo

for_lwtident=exprinittoexprfinaldo

expr

expr

done

done

raiseexn

raise_lwtexn

assertexpr

assert_lwtexpr

matchexprwith

match_lwtexprwith

|pattern1->expr1

|pattern1->expr1

|pattern2->expr2

|pattern2->expr2

...

...

|patternn->exprn

|patternn->exprn

whileexprdo

while_lwtexprdo

expr

expr

done

done

Backtrace support

When using Lwt, exceptions are not recorded by the ocaml runtime, and so you don't
get backtraces. However it is possible to get them when using the syntax extension. All you
have to do is to pass the -lwt-debug switch to camlp4:

Other modules of the core library

The core library contains several modules that only depend on
Lwt. The following naming convention is used in Lwt: when a
function takes as argument a function returning a thread that is going
to be executed sequentially, it is suffixed with ``_s''. And
when it is going to be executed concurrently, it is suffixed with
``_p''. For example, in the Lwt_list module we have:

Mutexes

Lwt_mutex provides mutexes for Lwt. Its use is almost the
same as the Mutex module of the thread library shipped with
OCaml. In general, programs using Lwt do not need a lot of
mutexes. They are only useful for serialising operations.

Lists

The Lwt_list module defines iteration and scanning functions
over lists, similar to the ones of the List module, but using
functions that return a thread. For example:

In iter_s f l, iter_s will call f on each elements
of l, waiting for completion between each element. On the
contrary, in iter_p f l, iter_p will call f on all
elements of l, then wait for all the threads to terminate.

Data streams

Lwt streams are used in a lot of places in Lwt and its sub
libraries. They offer a high-level interface to manipulate data flows.

A stream is an object which returns elements sequentially and
lazily. Lazily means that the source of the stream is touched only for new
elements when needed. This module contains a lot of stream
transformation, iteration, and scanning functions.

The common way of creating a stream is by using
Lwt_stream.from or by using Lwt_stream.create:

Note that streams are consumable. Once you take an element from a
stream, it is removed from it. So, if you want to iterate two times
over a stream, you may consider ``cloning'' it, with
Lwt_stream.clone. Cloned stream will return the same
elements in the same order. Consuming one will not consume the other.
For example:

Mailbox variables

The Lwt_mvar module provides mailbox variables. A mailbox
variable, also called a ``mvar'', is a cell which may contain 0 or 1
element. If it contains no elements, we say that the mvar is empty,
if it contains one, we say that it is full. Adding an element to a
full mvar will block until one is taken. Taking an element from an
empty mvar will block until one is added.

Mailbox variables are commonly used to pass messages between threads.

Note that a mailbox variable can be seen as a pushable stream with a
limited memory.

Running a Lwt program

Threads you create with Lwt always have the type
Lwt.t. If you want to write a program and run it this is not
enough. Indeed you don't know when a Lwt thread is terminated.

For example if your program is just:

let_=Lwt_io.printl"Hello, world!"

you have no guarantee that the thread writing "Hello, world!"
on the terminal will be terminated when the program exit. In order
to wait for a thread to terminate, you have to call the function
Lwt_main.run:

valLwt_main.run:'aLwt.t->'a

This functions wait for the given thread to terminate and returns
its result. In fact it does more than that; it also runs the
scheduler which is responsible for making threads progress when
events are received from the outside world.

So basically, when you write a Lwt program you must call
the toplevel the function Lwt_main.run. For instance:

let()=Lwt_main.run(Lwt_io.printl"Hello, world!")

Note that you must call Lwt_main.run only once at a time. It
cannot be used anywhere to get the result of a thread. It must only
be used in the entry point of your program.

The lwt.unix library

The package lwt.unix contains all unix dependent
modules of Lwt. Among all its features, it implements cooperative
versions of functions of the standard library and the unix library.

Unix primitives

The Lwt_unix provides cooperative system calls. For example,
the Lwt counterpart of Unix.read is:

valread:file_descr->string->int->int->intLwt.t

Lwt_io provides features similar to buffered channels of
the standard library (of type in_channel or
out_channel) but cooperatively.

Lwt_gc allows you to register a finaliser that returns a
thread. At the end of the program, Lwt will wait for all the
finaliser to terminate.

The Lwt scheduler

Threads doing IO may be put to sleep until some events are received by
the process. For example when you read from a file descriptor, you
may have to wait for the file descriptor to become readable if no
data are immediately available on it.

Lwt contains a scheduler which is responsible for managing
multiple threads waiting for events, and restart them when needed.
This scheduler is implemented by the two modules Lwt_engine
and Lwt_main. Lwt_engine is a low-level module, it
provides signatures for IO multiplexers as well as several builtin
implementations. Lwt supports by default multiplexing IO with
libev or Unix.select. The signature is given by the
class Lwt_engine.t.

libev is used by default on Unix, because it supports any
number of file descriptors while Unix.select supports only 1024 at
most, and is also much more efficient. On Windows Unix.select
is used because libev does not work properly. The user may
change at any time the backend in use.

The engine can also be used directly in order to integrate other
libraries with Lwt. For example GTK needs to be notified
when some events are received. If you use Lwt with GTK
you need to use the Lwt scheduler to monitor GTK
sources. This is what is done by the lwt.glib package.

The Lwt_main module contains the main loop of
Lwt. It is run by calling the function Lwt_main.run:

valLwt_main.run:'aLwt.t->'a

This function continously runs the scheduler until the thread passed
as argument terminates.

The logging facility

The package lwt.unix contains a module Lwt_log
providing loggers. It supports logging to a file, a channel, or to the
syslog daemon. You can also define your own logger by providing the
appropriate functions (function Lwt_log.make).

Several loggers can be merged into one. Sending logs on the merged
logger will send these logs to all its components.

it checks the log level before calling the logging function, so
the arguments are not computed if not needed

debugging logs can be removed at parsing time

By default, the syntax extension removes all logs with the level
debug. To keep them, pass the command line option
-lwt-debug to camlp4.

The Lwt.react library

The Lwt_react module provides helpers for using the react
library with Lwt. It extends the React module by adding
Lwt specific functions. It can be used as a replacement of
React. For example you can add at the beginning of your
program:

openLwt_react

instead of:

openReact

or:

moduleReact=Lwt_react

Among the added functionalities we have Lwt_react.E.next, which
takes an event and returns a thread which will wait until the next
occurence of this event. For example:

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 screeen
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:

vallimit:(unit->unitLwt.t)->'aReact.signal->'aReact.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 thread which sleeps
for 0.1 seconds, then there will be no more than 10 changes per
second. For example:

openLwt_reactletdrawx=(* Draw the screen *)...let()=(* The signal we are interested in: *)letsignal=...in(* The limited signal: *)letsignal'=S.limit(fun()->Lwt_unix.sleep0.1)signalin(* Redraw the screen each time the limited signal change: *)S.notify_pdrawsignal'

The lwt.text library provides functions to deal with text
mode (in a terminal). It is composed of the three following modules:

Lwt_text, which is the equivalent of Lwt_io
but for unicode text channels

Lwt_term, providing various terminal utilities, such as
reading a key from the terminal

Lwt_read_line, which provides functions to input text
from the user with line editing support

Text channels

A text channel is basically a byte channel with an encoding. Input
(resp. output) text channels decode (resp. encode) unicode characters
on the fly. By default, output text channels use transliteration, so
they will not fail because text you want to print cannot be encoded
in the system encoding.

For example, with your locale sets to ``C'', and the variable
name set to ``Jérémie'', you get:

#lwt()=Lwt_text.printlf"My name is %s"name;;MynameisJ?r?mie

Terminal utilities

The Lwt_term allow you to put the terminal in raw mode,
meaning that input is not buffered and characters are
returned as the user types them. For example, you can read a key with:

The second main feature of Lwt_term is the ability to print
text with styles. For example, to print text in bold and blue:

#openLwt_term;;#lwt()=printlc[fgblue;bold;text"foo"];;foo

If the output is not a terminal, then printlc will drop
styles, and act as Lwt_text.printl.

Read-line

Lwt_read_line provides a fully featured and fully
customisable read-line implementation. You can either use the
high-level and easy to use read_* functions, or use the
advanced Lwt_read_line.Control.read_* functions.

The second class of functions is a bit more complicated to use, but
allow control of a running read-line instance. For example you can
temporarily hide it to draw something, you can send it commands, fake
input, and the prompt is a signal so it can change dynamically.

Other libraries

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
detach the computation to a preemptive thread.

This is done by the module Lwt_preemptive of the
lwt.preemptive package which maintains a pool of system
threads. The main function is:

valdetach:('a->'b)->'a->'bLwt.t

detach f x will execute f x in another thread and
asynchronously wait for the result.

If you have to run Lwt code in another thread, you must use
the function Lwt_preemptive.run_in_main:

valrun_in_main:(unit->'aLwt.t)->'a

It works as follow:

it sends the function to the main thread and wait

the main thread execute the function

when it terminates the main thread sends back the result

the result is returned

Note that you cannot call Lwt_main.run in another system
thread, so you must use this function.

SSL support

The package lwt.ssl provides the module Lwt_ssl
which allows use of SSL asynchronously.

Glib integration

The lwt.glib embeds the glib main loop into the
Lwt one. This allows you to write GTK applications using Lwt. The
one thing you have to do is to call Lwt_glib.install at
the beginning of your program.

Writing stubs using Lwt

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.

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:

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:

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: