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: 24 Dec 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 = 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, and Lwt_ssl for SSL sockets. 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.

  • 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

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


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

Conflicts (2)

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