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: 28 Jun 2018

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 = Lwt_unix.((List.hd addresses).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.


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 and BuckleScript.

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 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, and on discuss.ocaml.org.


Contributing

  • We maintain easy starter issues. These are thoroughly explained and hyperlinked. We hope that this makes working on Lwt accessible even to relative OCaml beginners :)

  • 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.

  • The overall development plan can be found in the roadmap.

  • Ask us anything, whether it's about working on Lwt, or any question at all about it :)

  • The documentation always needs proofreading and fixes.

  • Despite a lot of progress, Lwt still needs more tests.

  • 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

Dependencies (5)

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

Conflicts (1)

  1. ocaml-variants = "4.02.1+BER"