raphael-proust on master
Lwt_domain: update to domainsli… Remove workflow that is not use… Merge pull request #971 from Su… (compare)
let rec f () = Lwt_main.yield () >>= fun () -> f ()
refs, and Lwt only gets involved when you call into it. if you call
f ()anywhere, OCaml will evaluate it to completion like in any other single-threaded program.
fas you defined it does not interact with Lwt at all. The
fdoesn't do anything special. It just waits for the result of
f ()(which never evaluates to a result), and wraps it in an already-completed promise once the result is available. It's basically the same as the
ref : 'a -> 'a reffunction. so, once the program above calls
loop (), it's stuck forever. it never calls
Lwt_main.run, or even that
timeoutallows things to run concurrently, and
f ()doesnt, is because
Lwt_unix.sleepimmediately returns a promise that won't be resolved for one second (as opposed to actually sleeping for one second). bind (
let%lwt) then immediately attaches a callback to that promise, and returns another promise that wont get resolved until (1) the sleep is done, and then (2) the callback runs, and (3) the promise returned by the callback is resolved
@aantron, now I understand why the previous code didn't work.
However, I'm 100% sure how @copy's code example works and what exactly
yield is doing -
the docs say:
yield () is a threads which suspends itself and then resumes as soon as possible and terminates.
Is it acting like an instantaneous "pause" between the consecutive evaluation steps? So the scheduler can stop it?
Also, if I had another function that was computing something -- say like:
let g n = if n = 0 then 0 else g n
then one way to make a "promise version" of this would be:
let rec g' n = Lwt.(Lwt_main.yield () >>= fun () -> if n = 0 then return 0 else g' n)
Would it be correct to say that, one cannot generically "lift"
g' and one has to write
refthing -- I had the wrong mental model that
lwtbasically uses a lightweight version of OS threads, but it essentially behaves in the same manner (you can terminate an OS thread at an arbitrary time, for example). Clearly, that's not the case.
Lwt_main.yield, it has type
unit -> unit Lwt.t. so what it's doing is creating a promise, in fact an unresolved one. so when you bind on it (
let%lwt), the code you are attaching gets stuffed into a callback that's attached to that unresolved promise
yieldpromise will be resolved by
Lwt_main.runthe next time it gets a chance to drive the I/O loop
Lwt_unix.sleep, they start some background I/O operation, that knows how to tell
Lwt_main.runthat it finished
Lwt_main.runwill happen later)
Lwt.wakeup_later), its just straight line ocaml code to load the callback list from the formerly pending promise, replace its state by resolved, and then run each callback in the list
Lwt.wakeup_latertraversing all these lists that are stored with pending promises
Lwt_unix.read, for example)
read(2)operation. when that completes, it resolves the promise it gave you, triggering what i just described above
Lwt_main.runis to block the process until the next such I/O promise gets resolved
Lwt_main.runputs the process to sleep. the real underlying I/O is meanwhile still running, in parallel
Lwt_main.runwakes up the process, resolves the associated promise, which triggers another phase of running as much code as possible
Lwt_main.yield ()btw is just the most trivial I/O promise possible.
yieldcreates a pending promise, then puts a function into the back of
Lwt_main.run's queue to resolve it right away. this allows
Lwt_main.runto first run any code in callbacks associated with other I/O promises that have resolved recently, then
yield ()promise, after draining the rest of the queue
I haven't followed the tutorial, I thought I'll just jump in and pick it up as I go :sweat_smile: , clearly a suboptimal approach. I was too fixated on solving the problem at hand rather than looking at the bigger picture.
I'll go through the tutorial now.
I think I follow most of your explanation. That said,
puts the process to sleep. the real underlying I/O is meanwhile still running, in parallel
has me a bit confused. Are there multiple OS processes here, with one sleeping and another one doing IO?
g, the answer is yes, you have to do it manually. however, ideally, this should be very rare
Lwt. the operators are provided by
let open Lwt.Infix in ...