caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: David House <dhouse@janestreet.com>
To: Dan Stark <interlock.public@gmail.com>
Cc: OCaml Mailing List <caml-list@inria.fr>
Subject: Re: [Caml-list] How is Async implemented?
Date: Tue, 3 Jun 2014 17:29:19 +0100	[thread overview]
Message-ID: <CAK=fH+gDpq_G9rwff=ex-2EDK9pF91yND2QGJAn74xNgB6novA@mail.gmail.com> (raw)
In-Reply-To: <CANQp=sT+7EgYnXaTZQfmUkYmWqgmODijbrsY25Huz=Eq=CK28g@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 3402 bytes --]

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 <interlock.public@gmail.com> 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
>
>
>
>
>
>
>
>
>
>
>
>
>

[-- Attachment #2: Type: text/html, Size: 4796 bytes --]

  reply	other threads:[~2014-06-03 16:29 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-03 15:39 Dan Stark
2014-06-03 16:29 ` David House [this message]
2014-06-03 20:59   ` Dan Stark
2014-06-03 22:33     ` Ashish Agarwal
2014-06-03 23:17       ` Dan Stark
2014-06-03 23:17     ` Yaron Minsky
2014-06-03 23:51       ` Dan Stark

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAK=fH+gDpq_G9rwff=ex-2EDK9pF91yND2QGJAn74xNgB6novA@mail.gmail.com' \
    --to=dhouse@janestreet.com \
    --cc=caml-list@inria.fr \
    --cc=interlock.public@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).