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
  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
  289. mirage-qubes-ipv4
  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. mpris = "0.1.1"
  303. mqtt >= "0.0.2"
  304. mrmime >= "0.5.0"
  305. multipart-form-data
  306. multipart_form >= "0.2.0" & < "0.4.0"
  307. multipart_form-lwt
  308. mwt
  309. named-pipe
  310. nanomsg
  311. nbd = "2.1.1" | >= "3.0.0"
  312. nbd-tool
  313. nbd-unix
  314. netchannel
  315. nocrypto >= "0.5.4"
  316. noise
  317. nottui-lwt
  318. nproc
  319. nsq < "0.2.4"
  320. obrowser
  321. obuilder < "0.4"
  322. obus >= "1.1.8" & < "1.2.1"
  323. ocaml-variants >= "4.00.1+mirage-unix" & < "4.00.1+open-types"
  324. ocluster < "0.2"
  325. ocluster-api < "0.2"
  326. ocplib-concur
  327. ocplib-resto
  328. ocsigen-start = "1.1.0" | >= "4.1.0" & < "4.7.0"
  329. ocsigen-toolkit = "1.1.0"
  330. ocsigenserver >= "2.10"
  331. odoc >= "2.0.0" & < "2.1.0"
  332. ojquery
  333. ojs-base < "0.6.0"
  334. opam-compiler < "0.2.0"
  335. opam-publish = "0.3.5"
  336. opam-sync-github-prs
  337. openflow < "0.2.0"
  338. opium >= "0.11.0" & < "0.19.0"
  339. opium_kernel
  340. order-i3-xfce
  341. ordma
  342. osc-lwt
  343. oskel >= "0.3.0"
  344. otetris
  345. ounit-lwt < "2.2.0"
  346. ounit2-lwt
  347. ox < "1.1.0"
  348. paf
  349. paf-cohttp
  350. pcap-format >= "0.3.3" & < "0.5.0"
  351. pgx_lwt
  352. pgx_lwt_mirage
  353. pgx_lwt_unix < "2.0"
  354. plotkicadsch
  355. ppx_defer >= "0.4.0"
  356. ppx_deriving_rpc
  357. ppx_json_types
  358. ppx_netblob
  359. ppx_rapper_lwt
  360. ppx_sqlexpr
  361. prof_spacetime
  362. prometheus
  363. prometheus-app
  364. promise_jsoo_lwt
  365. protocol-9p >= "0.10.0"
  366. protocol-9p-unix
  367. pvem_lwt_unix >= "0.0.2"
  368. qcow < "0.11.0"
  369. qcow-format
  370. qcow-tool
  371. qfs >= "0.5" & < "0.7"
  372. quests
  373. rashell
  374. rawlink < "2.1"
  375. rawlink-lwt
  376. redis-lwt
  377. resource-pooling
  378. resp >= "0.10.0"
  379. resp-mirage >= "0.10.0"
  380. resp-unix >= "0.10.0"
  381. resto
  382. resto-cohttp-client
  383. resto-cohttp-self-serving-client
  384. resto-cohttp-server
  385. resto-directory
  386. riak
  387. ringo-lwt
  388. river
  389. rpc >= "1.5.1" & < "7.1.0"
  390. rpclib-js
  391. rpclib-lwt
  392. sanddb >= "0.3.0"
  393. scgi
  394. sendmail-lwt
  395. session-cohttp-lwt
  396. session-cookie-lwt
  397. session-postgresql-lwt < "0.4.1"
  398. sessions
  399. shared-block-ring
  400. shared-memory-ring < "2.0.0"
  401. shared-memory-ring-lwt
  402. skkserv-lite
  403. slacko < "0.14.1"
  404. socket-daemon
  405. spin < "0.6.0"
  406. spotify-web-api < "0.2.1"
  407. sqlexpr
  408. statsd-client
  409. stog >= "0.16.0" & < "0.19.0"
  410. syndic >= "1.4" & < "1.6.0"
  411. tar-format >= "0.4.1"
  412. tar-mirage < "2.2.0"
  413. tar-unix
  414. tcpip >= "3.1.1" & < "4.0.0"
  415. telegraml
  416. testrunner
  417. tezos-p2p >= "11.0" & < "13.0"
  418. tezos-stdlib < "9.0"
  419. tezos-stdlib-unix < "9.0"
  420. tftp
  421. themoviedb
  422. tls >= "0.10.1" & < "0.16.0"
  423. tls-lwt < "0.17.4"
  424. tls-mirage
  425. tlstunnel >= "0.2.0"
  426. transmission-rpc
  427. tube
  428. tuntap >= "1.0.0" & < "2.0.0"
  429. typerex-lldb
  430. u2f
  431. usb
  432. uspf
  433. uspf-lwt
  434. utop >= "1.4.0"
  435. uwt >= "0.0.2"
  436. vchan >= "0.9.6" & < "2.0.0" | >= "2.0.3"
  437. vchan-unix
  438. vchan-xen
  439. vercel
  440. vhd-format >= "0.6.0" & < "0.9.1"
  441. vhd-format-lwt < "0.12.0"
  442. vhd-tool < "0.12.0"
  443. vmnet
  444. vpnkit >= "0.1.1"
  445. vue-jsoo < "0.3"
  446. webauthn
  447. websocket < "2.3"
  448. websocket-lwt = "2.11"
  449. xe-unikernel-upload
  450. xen-api-client < "0.9.14"
  451. xen-block-driver
  452. xen-evtchn
  453. xen-evtchn-unix
  454. xen-gnt
  455. xenctrl
  456. xenstore
  457. xenstore_transport
  458. xentropyd
  459. yurt != "0.3" & < "0.5"
  460. zbar
  461. zmq-lwt

Conflicts (2)

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