Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/ocsigen/lwt

OCaml promises and concurrent I/O
https://github.com/ocsigen/lwt

asynchronous concurency events fibers futures io lwt ocaml promises

Last synced: about 1 month ago
JSON representation

OCaml promises and concurrent I/O

Awesome Lists containing this project

README

        

# 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