1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
# Lwt
[![version][version]][releases] [![GitHub Actions status][github-actions-img]][github-actions]
[version]: https://img.shields.io/github/v/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
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.
<br/>
### 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
<br/>
## 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`
<br/>
## 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]: https://ocsigen.org/lwt/
[rwo-lwt]: https://github.com/dkim/rwo-lwt#readme
[mirage-tutorial]: https://mirage.io/docs/tutorial-lwt
[counter-server]: https://baturin.org/code/lwt-counter-server/
<br/>
## Contact
Open an [issue][issues], visit [Discord][discord] chat, ask on
[discuss.ocaml.org][discourse], or on [Stack Overflow][so].
Release announcements are made on [discuss.ocaml.org][discourse]. Watching the
repo for "Releases only" is also an option.
[so]: https://stackoverflow.com/questions/ask?tags=ocaml,lwt,ocaml-lwt
[discourse]: https://discuss.ocaml.org/tag/lwt
[issues]: https://github.com/ocsigen/lwt/issues/new
[discord]: https://discord.com/invite/cCYQbqN
<br/>
## 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
[contributing-md]: https://github.com/ocsigen/lwt/blob/master/docs/CONTRIBUTING.md#readme
<br/>
## 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/lwt-parallel) —
distributed computing
- [mwt](https://github.com/hcarty/mwt) — preemptive (system) thread pools
- [opium](https://github.com/rgrinberg/opium) —
web framework
- [lwt_domain](https://github.com/ocsigen/lwt_domain) — domain parallelism when
using Lwt with OCaml 5
|