Hi Yaron Yes, I do read your book and currently reading this chapter. And this is the reason I got interested of how it is implemented behind the scene. Thanks for all the help I got from here. Dan On Wed, Jun 4, 2014 at 12:17 AM, Yaron Minsky wrote: > For what it's worth, this gives a decent overview of Async (if I do > say so myself) > > > https://realworldocaml.org/v1/en/html/concurrent-programming-with-async.html > > This isn't quite right, but a good mental model is to think of Async > as being single threaded. Scheduler.go starts up the async scheduler > on the main thread, and you do indeed need to do that for any IO to > actually happen. > > y > > On Tue, Jun 3, 2014 at 4:59 PM, Dan Stark > wrote: > > Hi David > > > > Thank you very much for this comprehensive explanation. > > > > Can I also know who is responsible for the queue and scheduler? > > > > Are they created and maintained by OCaml thread (OCaml internal) or Async > > (3rd party library, which means Async create the job queue and has its > own > > scheduler)? > > > > In addition, will the compiler got involved in handling Deferred.t? > > > > I ask above questions because I felt quite curious about what is > happening > > in the followings: > > > > Suppose we have a normal function: > > > >> let f1 () = print_endline "hello"; whatever_result;; > > > > > > Normally, no matter what whatever_result is, when I do let _ = f1 ();;, > > print_endline "hello" will be executed, am I right? For example, finally > > returning an int or a record or a lazy.t, etc, "hello" would be printed > out. > > > > However, if I do > > > >> let f2 () = print_endline "hello"; return 1;; > > > > > > let _ = f2 ();; would do nothing unless I run the schedule let _ = > > ignore(Scheduler.go());; > > > > Since for f2 I am not using any other special creation function and the > only > > special bit is return 1 after print_endline, if the compiler doesn't get > > involved, how can compiler know the whole application of f2() should be > in > > future execution? > > > > Sorry for my above verbose questions if they are boring. I am just > trying to > > understand more and I guess eventually I will look into the code once I > > grasp the big picture. > > > > thanks > > > > Dan > > > > > > > > > > > > > > > > > > > > On Tue, Jun 3, 2014 at 5:29 PM, David House > wrote: > >> > >> There is a queue of jobs in the scheduler. The scheduler runs the jobs > one > >> by one. Jobs may schedule other jobs. A job is a pair of ['a * 'a -> > unit]. > >> > >> There's a thing called a deferred. ['a Deferred.t] is an initially empty > >> box that may become filled later with something of type ['a]. There is a > >> similar type called ['a Ivar.t] -- the difference is that ivars have a > >> function to actually fill in the value, whereas deferreds do not: a > deferred > >> is a "read-only" view on an ivar. > >> > >> You can wait on a deferred using bind. Doing [x >>= f] mutates the > >> deferred x to add f as a "handler". When a deferred is filled, it adds > a job > >> to the scheduler for each handler it has. > >> > >> Doing [Deferred.return 1] allocates a deferred which is already filled > and > >> has no handlers. Binding on that will immediately schedule a job to run > your > >> function. (The job is still scheduled though, rather than being run > >> immediately, to ensure that you don't have an immediate context switch > -- in > >> async, the only context switch points are the binds.) > >> > >> The primitive operations that block are replaced with functions that > >> return deferreds, and go do their work in a separate thread. There's a > >> thread pool to make sure you don't use infinity threads. (I think the > >> default cap is 50 threads.) I think yes, async does depend on -thread. > >> > >> There is an important optimisation: if you want to read or write to > >> certain file descriptors, that doesn't use a thread. Instead there's a > >> central list of such file descriptors. There's also a central list of > all > >> "timer events" (e.g. deferreds that become deferred after some amount of > >> time). The scheduler actually is based around a select loop: it does the > >> following: > >> > >> run all the jobs > >> if more jobs have been scheduled, run those too > >> keep going until there are no more jobs, or we hit the > >> maximum-jobs-per-cycle cap > >> sleep using select until one read fd is read, or a write fd is ready, > or a > >> timer event is due to fire > >> do that thing > >> > >> There's also a way to manually interrupt the scheduler. Blocking > >> operations other than reading/writing to fds do this: they run in a > thread, > >> grab the async scheduler lock, fill in an ivar, then wake up the > scheduler > >> to ensure timely running of the jobs they just scheduled. The async > >> scheduler lock is necessary because the scheduler itself is not > re-entrant: > >> you cannot have multiple threads modifying the scheduler's internals. > >> > >> > >> On 3 June 2014 16:39, Dan Stark wrote: > >>> > >>> Hi all > >>> > >>> I am trying to get a rough overview of how Async is implemented (or the > >>> idea behind it) before I really dig into its source code. > >>> > >>> I have the following questions: > >>> > >>> Q1: Is Async event-loop like? > >>> > >>> From the API and some docs for Async's usage, I feel it is quite like a > >>> event-loop. > >>> > >>> You create Deferred.t and it might be added to a queue and a scheduler > >>> behind might be adjusting the order of running for all Deferred.t in > the > >>> queue. > >>> > >>> Am I correct? > >>> > >>> Q2: Deferred.return and Deferred.bind > >>> > >>> If I say > >>> > >>>> Deferred.return 1 > >>> > >>> > >>> It will returns me a Deferred.t, but inside the function return or bind > >>> somehow an "event" is implicitly added to the default queue for > scheduling, > >>> right? > >>> > >>> If I am correct above, > >>> > >>> Q3: Is Async depending on -thread? The queue or scheduler needs > compiler > >>> support? > >>> > >>> I just need to understand the whole picture in a rough way first. > >>> > >>> Thanks > >>> > >>> Dan > >>> > >>> > >>> > >>> > >>> > >>> > >>> > >>> > >>> > >>> > >>> > >>> > >> > > >