lwt

Promises and event-driven I/O
README

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* ... 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 provides promises...

  • ...and a few pure-OCaml helpers, such as promise-friendly mutexes,
    condition variables, and 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.

  • The PPX syntax allows using all of the above without going crazy!

  • There are also some other helpers, such as Lwt_react for reactive
    programming. See the table of contents on the linked manual pages!

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.

  • Mirage has a nicely-written Lwt tutorial.

  • An example of a simple server written in Lwt.

  • Concurrent Programming with 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.

Contact

Open an issue, visit Discord chat, ask on
discuss.ocaml.org, or on Stack Overflow.

Release announcements are made in /r/ocaml, and on
discuss.ocaml.org. Watching the repo for "Releases only" is also an
option.

Contributing

  • 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 us anything, whether it's about working on Lwt, or any
    question at all about it :)

  • The documentation always needs proofreading and fixes.

  • You are welcome to pick up any other issue, review a PR, add
    your opinion, etc.

  • Any feedback is welcome, including how to make contributing easier!

Libraries to use with Lwt

Install
Published
24 Jun 2022
Sources
5.6.0.tar.gz
md5=e63979ee40a80d5b9e9e5545f33323b4
sha512=d616389bc9e0da11f25843ab7541ac2d40c9543700a89455f14115b339bbe58cef2b8acf0ae97fd54e15a4cb93149cfe1ebfda301aa93933045f76b7d9344160
Dependencies
ocamlfind
dev & >= "1.7.3-1"
ocaml
>= "4.08"
dune
>= "1.8.0"
cppo
build & >= "1.1.0"
Reverse Dependencies
0install
>= "2.15.1"
amqp-client
>= "0.9.0" & < "1.0.2" | >= "1.1.0"
arakoon
< "1.8.6" | >= "1.8.8"
arp
>= "2.3.1"
arp-mirage
>= "2.2.1"
bap
< "1.0.0"
bap-server
< "0.2.0"
biocaml
= "0.4.0"
bistro
>= "0.4.0"
bun
>= "0.3.3"
camltc
= "0.9.5" | >= "0.9.7.0"
capnp-rpc-unix
>= "0.9.0"
caqti-lwt
>= "0.11.0"
chamo
>= "3.0"
charrua-client
>= "1.3.0"
charrua-unix
>= "0.3" & != "0.10"
cowabloga
>= "0.2.2"
crunch
>= "2.0.0"
ctypes
>= "0.15.0"
current_rpc
>= "0.4"
data-encoding
< "0.1.1"
datakit-client
>= "0.11.0"
devkit
>= "1.2"
dht
< "0.2.0"
dns
>= "0.19.1" & < "0.20.1"
dns-cli
>= "4.6.3"
dns-forward
>= "0.9.0"
docteur
>= "0.0.2"
docteur-unix
>= "0.0.5"
doi2bib
>= "0.5.1"
ez_api
>= "1.2.0"
ezjs_min
< "0.2"
ezjsonm
>= "0.4.2" & < "0.5.0"
fat-filesystem
>= "0.12.0"
flowtype
>= "0.72.0"
frenetic
< "2.0.0"
gdbprofiler
>= "0.3"
git
!= "1.4.3" & != "1.7.2"
git-mirage
>= "3.0.0"
git-unix
= "1.11.1" | >= "3.0.0"
github-hooks
< "0.2.0" | >= "0.4.0"
github-unix
>= "4.4.0"
hardcaml
< "1.1.0"
hiredis
!= "0.4"
horned_worm
< "0.3.1"
http-multipart-formdata
>= "2.0.0" & < "3.0.0"
hvsock
>= "1.0.2"
i3ipc
>= "0.1.4"
inotify
>= "2.4"
inquire
< "0.3.0"
iocaml
< "0.4.6"
iocaml-kernel
>= "0.4.3" & < "0.4.6"
irmin
< "0.9.6" | = "0.9.10" | >= "0.11.0"
irmin-fs
>= "2.3.0"
irmin-git
>= "2.3.0"
irmin-graphql
>= "2.3.0"
irmin-http
>= "2.3.0"
irmin-mem
>= "2.3.0"
irmin-test
>= "2.3.0"
irmin-unix
>= "2.3.0"
irmin-watcher
>= "0.3.0"
jupyter
>= "2.3.0"
kafka
>= "0.3" & < "0.5"
ke
>= "0.5"
ketrew
>= "3.2.0"
kinetic-client
< "0.0.3" | >= "0.0.9"
lablqml
< "0.6"
lambda-term
>= "1.13"
learn-ocaml
>= "0.13.0"
links
!= "0.9"
lwt-binio
< "0.2.0"
lwt-zmq
< "1.0.0"
lwt_glib
>= "1.0.1"
lwt_log
>= "1.1.0"
lwt_react
>= "1.0.1"
lwt_ssl
>= "1.0.1"
mariadb
< "0.5.1"
markup
= "0.7.6"
mirage
>= "0.4.1" & != "0.6.1" & < "0.8.0" | >= "0.10.0" & < "2.7.0"
mirage-block
< "1.0.0" | >= "2.0.0"
mirage-block-unix
< "2.3.0" | = "2.8.2" | >= "2.13.0"
mirage-channel
>= "4.0.0"
mirage-clock-unix
>= "1.3.0" & < "3.0.0"
mirage-console
>= "3.0.0"
mirage-device
>= "2.0.0"
mirage-dns
< "3.0.0"
mirage-flow
>= "1.0.3" & < "1.2.0" | >= "2.0.0"
mirage-flow-lwt
< "1.3.0" | >= "1.5.0"
mirage-fs
>= "3.0.0"
mirage-fs-unix
< "1.1.1" | >= "1.3.0"
mirage-kv
>= "3.0.0"
mirage-logs
!= "0.3.0"
mirage-net
>= "3.0.1"
mirage-os-shim
>= "3.0.0"
mirage-protocols
>= "4.0.0" & < "8.0.0"
mirage-qubes
< "0.2" | >= "0.4"
mirage-runtime
>= "3.7.0"
mirage-stack
>= "2.0.0" & < "4.0.0"
mirage-time
>= "2.0.0"
mirage-unix
>= "3.0.0"
mirage-www
>= "1.1.0"
mqtt
>= "0.0.2"
mrmime
>= "0.5.0"
multipart_form
>= "0.2.0" & < "0.4.0"
nbd
= "2.1.1" | >= "4.0.3"
nocrypto
>= "0.5.4"
nsq
>= "0.4.0"
obus
>= "1.2.1"
ocaml-variants
>= "4.00.1+mirage-unix" & < "4.00.1+open-types"
ocsigenserver
>= "2.10"
odoc
>= "2.0.0" & < "2.1.0"
openflow
< "0.2.0"
opium
>= "0.11.0" & != "0.16.0"
ordma
>= "0.0.3"
oskel
>= "0.3.0"
ounit-lwt
< "2.2.0"
ox
< "1.1.0"
pcap-format
>= "0.3.3" & < "0.5.0"
plebeia
>= "2.0.0"
plotkicadsch
>= "0.4.0"
ppx_defer
>= "0.4.0"
protocol-9p
>= "0.10.0"
qcow
>= "0.8.1"
qfs
= "0.5" | >= "0.7"
rawlink
>= "1.0"
resp-mirage
>= "0.10.0"
resp-unix
>= "0.10.0"
resto-cohttp-server
>= "0.4" & < "0.6" | >= "0.9"
rpc
>= "1.5.1" & < "7.1.0"
shared-block-ring
< "2.3.0" | >= "3.0.0"
shared-memory-ring
>= "1.2.0" & < "2.0.0"
sihl
< "0.2.0"
socket-daemon
< "0.3.0"
spin
< "0.8.0"
sqlexpr
= "0.7.1" | >= "0.9.0"
stog
>= "0.16.0"
syndic
>= "1.4" & < "1.6.0"
tar-format
>= "0.4.1"
tcpip
>= "3.1.1" & < "3.4.1" | >= "4.1.0"
tezos-base
>= "13.0"
tezos-clic
>= "13.0"
tezos-crypto
>= "13.0"
tezos-error-monad
>= "8.0" & < "9.0" | >= "13.0"
tezos-p2p
>= "11.0" & < "13.0"
tezos-stdlib-unix
>= "8.0" & < "9.0" | >= "13.0"
tls
= "0.10.1" | >= "0.10.6"
tube
>= "4.3.0"
tuntap
>= "1.0.0" & < "1.7.0" | >= "2.0.0"
utop
>= "1.4.0"
uwt
>= "0.3.0"
vchan
>= "0.9.7" & < "2.0.0" | >= "2.0.3"
vhd-format
>= "0.7.0" & < "0.8.0"
vhd-format-lwt
>= "0.12.0"
vhd-tool
< "0.12.0"
vmnet
>= "1.3.2"
vpnkit
>= "0.2.0"
websocket
< "2.3"
xen-api-client
< "0.9.14"
xen-evtchn
< "1.0.6" | >= "2.0.0"
xen-gnt
>= "2.2.3"
xenctrl
< "0.9.29" | >= "0.9.32"
xenstore
>= "1.3.0"
yurt
< "0.3"