package lwt

  1. Overview
  2. Docs

Description

A promise is a value that may become determined in the future.

Lwt provides typed, composable promises. Promises that are resolved by I/O are resolved by Lwt in parallel.

Meanwhile, OCaml code, including code creating and waiting on promises, runs in a single thread by default. This reduces the need for locks or other synchronization primitives. Code can be run in parallel on an opt-in basis.

Published: 21 Jul 2017

README

Lwt   

Lwt is OCaml's concurrent programming library. 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:

let () =
  let request =
    let%lwt addresses = Lwt_unix.getaddrinfo "google.com" "80" [] in
    let google = (List.hd addresses).Lwt_unix.ai_addr in

    Lwt_io.(with_connection google (fun (incoming, outgoing) ->
      let%lwt () = write outgoing "GET / HTTP/1.1\r\n" in
      let%lwt () = write outgoing "Connection: close\r\n\r\n" in
      let%lwt response = read incoming in
      Lwt.return (Some response)))
  in

  let timeout =
    let%lwt () = 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 -package lwt.ppx -linkpkg -o request example.ml
   ./request *)

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.


Installing

  1. Use your system package manager to install a development libev package, 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 great 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.

  • Some examples are also available in Lwt's doc/examples.

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 Gitter chat, ask in #ocaml, on discuss.ocaml.org, or on Stack Overflow. Please do ask! Even apparently simple questions often end up educating other users, not to mention enlightening the maintainers!

Subscribe to the announcements issue to get news about Lwt releases. It is less noisy than watching the whole repository. Announcements are also made in /r/ocaml, on the OCaml mailing list, and on discuss.ocaml.org.


Contributing

What counts as a contribution to Lwt? All kinds of things make the project better, and are very much appreciated:

  • Asking anything. This helps everyone understand Lwt, including long-time maintainers!

  • Making or requesting edits to the docs, or just reading them.

  • Reading any issue or PR, and, optionally, adding your opinion or requesting clarification.

  • Explaining how to make Lwt easier to contribute to, finding problems with the contributing docs, etc.

  • Helping other people with Lwt, whether in this repo, or elsewhere in the world.

  • Writing or clarifying test cases.

  • And, of course, the traditional kind of contribution, picking up issues and writing code :)

Contributing to Lwt is not only for OCaml "experts!" If you are near the beginning of your OCaml journey, we'd love to give you a little help by recommending appropriate issues, or even just chatting about Lwt or OCaml. Newcomers make valuable contributions, that maintainers often learn from – not the least because newcomers bring a fresh, valuable perspective :) Don't be afraid to ask anything.

We hope you'll join us to work in a friendly community around Lwt :) On behalf of all users of, and contributors to, Lwt: Thank you! :tada:

Resources

There are several resources to help you get started:

  • If you'd like to ask a question, or otherwise talk, there is the contact information.

  • Lwt maintains a list of easy issues, which you can use to try out the code contribution workflow. This list works two ways! Please contribute to it: if you find something that needs a fix, open an issue. It might be an easy issue that another contributor would love to solve :)

  • CONTRIBUTING.md contains optional tips for working on the code of Lwt, instructions on how to check the code out, and a high-level outline of the code base.

  • The project roadmap contains a list of long-term, large-scale projects, so you can get an idea of where Lwt is headed, as a whole. Planned upcoming releases are also listed there.

  • Watch this repository :)


License

Lwt is released under the LGPL, with an OpenSSL linking exception. See COPYING.

Dependencies (7)

  1. result
  2. ppx_tools_versioned >= "5.0.1"
  3. ocaml-migrate-parsetree < "2.0.0"
  4. ocamlfind build & >= "1.5.0"
  5. jbuilder >= "1.0+beta10"
  6. cppo build & >= "1.1.0"
  7. ocaml >= "4.02.0" & < "4.08.0"

Dev Dependencies

None

  1. 0install >= "2.14"
  2. albatross
  3. alcotest-lwt
  4. alcotest-mirage
  5. ambient-context-lwt
  6. amqp-client >= "0.9.0" & < "1.0.2" | >= "1.1.0"
  7. amqp-client-lwt
  8. angstrom-lwt-unix
  9. anthill
  10. anycache-lwt
  11. arakoon < "1.8.6" | >= "1.8.8"
  12. archi-lwt
  13. arp >= "2.3.1"
  14. arp-mirage
  15. awa-lwt
  16. awa-mirage < "0.2.0"
  17. aws < "1.0.0"
  18. aws-s3-lwt
  19. awsm-lwt
  20. azure-cosmos-db
  21. baardskeerder
  22. balancer
  23. bap < "1.0.0"
  24. bap-server < "0.3.0"
  25. bimage-lwt
  26. biocaml = "0.4.0"
  27. bistro < "0.5.0"
  28. brotli < "1.2.0"
  29. brozip
  30. builder
  31. bun >= "0.3.3"
  32. c3
  33. calculon
  34. camltc < "0.9.5"
  35. canary
  36. capnp-rpc-lwt < "1.2.3"
  37. capnp-rpc-unix >= "0.9.0" & < "1.2.3"
  38. caqti-lwt < "0.11.0"
  39. carton-git
  40. carton-lwt
  41. channel
  42. charrua-client-lwt < "1.2.0"
  43. charrua-client-mirage < "1.2.0"
  44. charrua-core < "0.3"
  45. charrua-unix >= "0.3" & < "0.11.0" | >= "0.11.2"
  46. cmdtui-lambda-term
  47. coclobas
  48. cohttp-lwt < "6.0.0~alpha2"
  49. cohttp-lwt-jsoo
  50. cohttp-lwt-unix
  51. cohttp-lwt-unix-nossl
  52. cohttp-lwt-unix-ssl
  53. cohttp-mirage
  54. comby
  55. comby-semantic
  56. conan-lwt
  57. conduit-lwt
  58. conduit-lwt-unix
  59. cowabloga >= "0.2.2"
  60. crunch >= "2.0.0"
  61. cstruct-lwt
  62. csv-lwt
  63. csvprovider
  64. ctypes >= "0.6.0" & < "0.15.0"
  65. ctypes-foreign >= "0.21.1"
  66. curly < "0.2.0"
  67. current_docker < "0.6.4"
  68. current_examples < "0.6.4"
  69. current_git < "0.6.4"
  70. current_github < "0.6.4"
  71. current_gitlab < "0.6.4"
  72. current_ocluster < "0.2"
  73. current_slack < "0.6.4"
  74. current_web < "0.6.4"
  75. DkSDKFFIOCaml_Std
  76. dap
  77. data-encoding < "0.1.1"
  78. datakit
  79. datakit-bridge-github
  80. datakit-bridge-local-git
  81. datakit-ci
  82. datakit-client >= "0.11.0"
  83. datakit-github
  84. datakit-server
  85. devkit
  86. dht < "0.2.0"
  87. distributed = "0.4.0"
  88. dkim-mirage
  89. dns >= "0.19.1" & < "1.0.0"
  90. dns-forward >= "0.9.0"
  91. dns-forward-lwt-unix
  92. dns-lwt
  93. dnssd
  94. docker_hub
  95. dream
  96. dream-httpaf
  97. dream-pure
  98. dropbox
  99. dune_watch
  100. earlybird < "1.0.0"
  101. elasticsearch-cli < "0.4"
  102. eliom = "6.3.0"
  103. eris-lwt
  104. ethernet
  105. ezcurl-lwt
  106. ezirmin
  107. ezjsonm >= "0.4.2" & < "0.5.0"
  108. ezjsonm-lwt
  109. ezresto
  110. ezresto-directory
  111. faraday-lwt
  112. faraday-lwt-unix
  113. fat-filesystem >= "0.12.0"
  114. fiber-lwt
  115. flowtype >= "0.62.0" & < "0.72.0"
  116. frenetic < "2.0.0"
  117. fswatch_lwt
  118. fuseau-lwt
  119. gamepad
  120. gdb
  121. gdbprofiler < "0.3"
  122. git != "1.4.3" & != "1.7.2"
  123. git-paf
  124. git-unix = "1.11.1" | >= "3.0.0" & < "3.10.0"
  125. github
  126. github-hooks
  127. github-unix >= "4.4.0"
  128. gitlab-unix
  129. gluten-lwt < "0.4.0"
  130. gluten-lwt-unix < "0.4.0"
  131. gluten-mirage < "0.4.0"
  132. graphql-lwt
  133. gufo
  134. h2-lwt < "0.10.0"
  135. h2-lwt-unix < "0.10.0"
  136. h2-mirage
  137. happy-eyeballs-lwt
  138. happy-eyeballs-mirage
  139. hardcaml < "1.1.0"
  140. hardcaml-examples >= "0.3.0"
  141. hardcaml-framework
  142. hardcaml-waveterm
  143. hiredis < "0.6"
  144. hl_yaml
  145. horned_worm < "0.3.1"
  146. http-lwt-client
  147. http-multipart-formdata >= "2.0.0" & < "3.0.0"
  148. http2https
  149. httpaf-lwt-unix
  150. hvsock < "1.0.2"
  151. i3ipc
  152. imaplet-lwt
  153. influxdb-lwt
  154. inotify >= "2.4"
  155. inquire < "0.3.0"
  156. iocaml < "0.4.6"
  157. iocaml-kernel >= "0.4.3"
  158. iocamljs-kernel
  159. ip2location
  160. ip2locationio
  161. ipv6-multicast < "0.9"
  162. irc-client-lwt
  163. irc-client-lwt-ssl
  164. irc-client-tls
  165. irmin < "0.9.6" | = "0.9.10" | >= "0.11.0" & < "2.7.0"
  166. irmin-bench < "2.7.0"
  167. irmin-chunk < "2.7.0"
  168. irmin-containers < "2.7.0"
  169. irmin-fs >= "2.3.0" & < "2.7.0"
  170. irmin-git >= "2.3.0" & < "2.7.0"
  171. irmin-graphql >= "2.3.0" & < "2.7.0"
  172. irmin-http >= "2.3.0" & < "2.7.0"
  173. irmin-indexeddb
  174. irmin-layers < "2.7.0"
  175. irmin-mem >= "2.3.0"
  176. irmin-mirage-git >= "2.3.0" & < "2.7.0"
  177. irmin-mirage-graphql >= "2.3.0" & < "2.7.0"
  178. irmin-pack < "2.7.0"
  179. irmin-test >= "2.3.0" & < "2.7.0"
  180. irmin-unix >= "2.3.0" & < "2.7.0"
  181. irmin-watcher
  182. jitsu
  183. joolog
  184. jose < "0.9.0"
  185. js_of_ocaml < "3.0"
  186. js_of_ocaml-lwt
  187. jsoo_broadcastchannel
  188. jsoo_router
  189. jsoo_storage
  190. jupyter < "2.3.0"
  191. jupyter-archimedes < "2.3.2"
  192. jupyter-kernel
  193. KaSim >= "4.0.0"
  194. kafka >= "0.3" & < "0.5"
  195. kafka_lwt
  196. ke >= "0.5"
  197. ketrew >= "3.2.0"
  198. kinetic-client < "0.0.9"
  199. lablqml < "0.6"
  200. lambda-runtime
  201. lambda-term >= "1.11" & < "1.13"
  202. launchd
  203. letsencrypt
  204. letsencrypt-app
  205. letsencrypt-dns
  206. libres3
  207. links < "0.9.5"
  208. lru_cache < "v0.16.0"
  209. lwt-binio
  210. lwt-canceler
  211. lwt-dllist
  212. lwt-exit
  213. lwt-parallel >= "0.1.2"
  214. lwt-pipe
  215. lwt-pipeline
  216. lwt-watcher
  217. lwt-zmq
  218. lwt_camlp4
  219. lwt_domain < "0.3.0"
  220. lwt_eio < "0.4"
  221. lwt_glib >= "1.0.1"
  222. lwt_log < "1.1.0"
  223. lwt_named_threads
  224. lwt_ppx
  225. lwt_ppx_let
  226. lwt_react >= "1.0.1"
  227. lwt_ssl >= "1.0.1"
  228. macaque_lwt
  229. maki
  230. mariadb < "0.5.1"
  231. markup = "0.7.6"
  232. markup-lwt
  233. mdx
  234. mechaml
  235. metrics-influx
  236. metrics-lwt
  237. metrics-mirage
  238. metrics-unix
  239. mindstorm-lwt
  240. mirage < "0.9.1" | >= "0.10.0" & < "2.7.0"
  241. mirage-block < "1.0.0"
  242. mirage-block-ccm
  243. mirage-block-lwt
  244. mirage-block-ramdisk
  245. mirage-block-solo5
  246. mirage-block-unix < "2.8.3"
  247. mirage-block-xen
  248. mirage-bootvar-solo5 >= "0.2.0"
  249. mirage-bootvar-unix
  250. mirage-bootvar-xen >= "0.4.0"
  251. mirage-channel-lwt
  252. mirage-clock-freestanding < "3.0.0"
  253. mirage-clock-lwt
  254. mirage-clock-unix >= "1.2.0" & < "3.0.0"
  255. mirage-console >= "2.1.1" & < "2.2.0"
  256. mirage-console-lwt
  257. mirage-console-solo5 >= "0.2.0"
  258. mirage-console-unix >= "2.2.0" & < "3.0.0"
  259. mirage-console-xen >= "5.0.0"
  260. mirage-console-xen-backend < "3.0.1"
  261. mirage-console-xen-cli
  262. mirage-dns < "3.0.0"
  263. mirage-entropy < "0.5.0"
  264. mirage-entropy-unix
  265. mirage-entropy-xen != "0.2.0"
  266. mirage-flow >= "1.0.3" & < "1.2.0"
  267. mirage-flow-lwt
  268. mirage-flow-rawlink
  269. mirage-flow-unix < "2.0.0"
  270. mirage-fs-lwt
  271. mirage-fs-unix != "1.2.1"
  272. mirage-http
  273. mirage-http-unix
  274. mirage-http-xen
  275. mirage-kv-lwt
  276. mirage-kv-unix < "3.0.0"
  277. mirage-logs
  278. mirage-nat < "3.0.0"
  279. mirage-net-fd
  280. mirage-net-lwt
  281. mirage-net-macosx
  282. mirage-net-solo5
  283. mirage-net-unix
  284. mirage-net-xen
  285. mirage-os-shim >= "3.0.0"
  286. mirage-profile
  287. mirage-protocols-lwt
  288. mirage-qubes < "0.9.4"
  289. mirage-qubes-ipv4 < "0.9.4"
  290. mirage-random-stdlib >= "0.1.0"
  291. mirage-solo5
  292. mirage-stack-lwt
  293. mirage-time-lwt
  294. mirage-time-unix < "2.0.0"
  295. mirage-types-lwt < "3.7.1"
  296. mirage-unix
  297. mirage-vnetif
  298. mirage-vnetif-stack
  299. mirage-www >= "1.1.0"
  300. mirage-xen
  301. mirror
  302. moonpool-lwt
  303. mpris = "0.1.1"
  304. mqtt = "0.0.2"
  305. mrmime >= "0.5.0"
  306. multipart-form-data
  307. multipart_form >= "0.2.0" & < "0.4.0"
  308. multipart_form-lwt < "0.6.0"
  309. mwt
  310. named-pipe
  311. nanomsg
  312. nbd = "2.1.1" | >= "3.0.0"
  313. nbd-tool
  314. nbd-unix
  315. netchannel
  316. nocrypto >= "0.5.4"
  317. noise
  318. nottui-lwt
  319. nproc
  320. nsq < "0.2.4"
  321. obrowser
  322. obuilder < "0.4"
  323. obus >= "1.1.8" & < "1.2.1"
  324. ocaml-variants >= "4.00.1+mirage-unix" & < "4.00.1+open-types"
  325. ocluster < "0.2"
  326. ocluster-api < "0.2"
  327. ocplib-concur
  328. ocplib-resto
  329. ocsigen-start = "1.1.0" | >= "4.1.0" & < "4.7.0"
  330. ocsigen-toolkit = "1.1.0"
  331. ocsigenserver >= "2.10"
  332. odoc >= "2.0.0" & < "2.1.0"
  333. ojquery
  334. ojs-base < "0.6.0"
  335. opam-compiler < "0.2.0"
  336. opam-publish = "0.3.5"
  337. opam-sync-github-prs
  338. openflow < "0.2.0"
  339. opium >= "0.11.0" & < "0.19.0"
  340. opium_kernel
  341. order-i3-xfce
  342. ordma
  343. osc-lwt
  344. oskel >= "0.3.0"
  345. otetris
  346. ounit-lwt < "2.2.0"
  347. ounit2-lwt
  348. ox < "1.1.0"
  349. paf
  350. paf-cohttp
  351. pcap-format >= "0.3.3" & < "0.5.0"
  352. pgx_lwt
  353. pgx_lwt_mirage
  354. pgx_lwt_unix < "2.0"
  355. plotkicadsch
  356. ppx_defer >= "0.4.0"
  357. ppx_deriving_rpc
  358. ppx_json_types
  359. ppx_netblob
  360. ppx_rapper_lwt
  361. ppx_sqlexpr
  362. prof_spacetime
  363. prometheus
  364. prometheus-app
  365. promise_jsoo_lwt
  366. protocol-9p >= "0.10.0"
  367. protocol-9p-unix
  368. pvem_lwt_unix >= "0.0.2"
  369. qcow < "0.11.0"
  370. qcow-format
  371. qcow-tool
  372. qfs >= "0.5" & < "0.7"
  373. quests
  374. rashell
  375. rawlink < "2.1"
  376. rawlink-lwt
  377. redis-lwt
  378. resource-pooling
  379. resp >= "0.10.0"
  380. resp-mirage >= "0.10.0"
  381. resp-unix >= "0.10.0"
  382. resto
  383. resto-cohttp-client
  384. resto-cohttp-self-serving-client
  385. resto-cohttp-server
  386. resto-directory
  387. riak
  388. ringo-lwt
  389. river
  390. rpc >= "1.5.1" & < "7.1.0"
  391. rpclib-js
  392. rpclib-lwt
  393. sanddb >= "0.3.0"
  394. scgi
  395. sendmail-lwt
  396. session-cohttp-lwt
  397. session-cookie-lwt
  398. session-postgresql-lwt < "0.4.1"
  399. sessions
  400. shared-block-ring
  401. shared-memory-ring < "2.0.0"
  402. shared-memory-ring-lwt
  403. skkserv-lite
  404. slacko < "0.14.1"
  405. socket-daemon
  406. spin < "0.6.0"
  407. spotify-web-api < "0.2.1"
  408. sqlexpr
  409. statsd-client
  410. stog >= "0.16.0" & < "0.19.0"
  411. syndic >= "1.4" & < "1.6.0"
  412. tar-format >= "0.4.1"
  413. tar-mirage < "2.2.0"
  414. tar-unix
  415. tcpip >= "3.1.1" & < "4.0.0"
  416. telegraml
  417. testrunner
  418. tezos-p2p >= "11.0" & < "13.0"
  419. tezos-stdlib < "9.0"
  420. tezos-stdlib-unix < "9.0"
  421. tftp
  422. themoviedb
  423. tls >= "0.10.1" & < "0.16.0"
  424. tls-lwt < "0.17.4"
  425. tls-mirage
  426. tlstunnel >= "0.2.0"
  427. transmission-rpc
  428. tube
  429. tuntap >= "1.0.0" & < "2.0.0"
  430. typerex-lldb
  431. u2f
  432. usb
  433. uspf
  434. uspf-lwt
  435. utop >= "1.4.0"
  436. uwt >= "0.0.2"
  437. vchan >= "0.9.6" & < "2.0.0" | >= "2.0.3"
  438. vchan-unix
  439. vchan-xen
  440. vercel
  441. vhd-format >= "0.6.0" & < "0.9.1"
  442. vhd-format-lwt < "0.12.0"
  443. vhd-tool < "0.12.0"
  444. vmnet
  445. vpnkit >= "0.1.1"
  446. vue-jsoo < "0.3"
  447. webauthn
  448. websocket < "2.3"
  449. websocket-lwt = "2.11"
  450. xe-unikernel-upload
  451. xen-api-client < "0.9.14"
  452. xen-block-driver
  453. xen-evtchn
  454. xen-evtchn-unix
  455. xen-gnt
  456. xenctrl
  457. xenstore
  458. xenstore_transport
  459. xentropyd
  460. yurt != "0.3" & < "0.5"
  461. zbar
  462. zmq-lwt

Conflicts (2)

  1. dune >= "1.7.0"
  2. ocaml-variants = "4.02.1+BER"