Boost logo

Boost :

Subject: Re: [boost] Asynchronous library now in Boost Library Incubator
From: Christophe Henry (christophe.j.henry_at_[hidden])
Date: 2016-11-30 15:28:36


On 11/30/2016 08:10 AM, Biddiscombe, John A. wrote:
> Christophe
>
>>
> I don't think the libraries have the same goals (or at least it seems to me so). Asynchronous is first of all an architecture tool focusing on organizing a whole application into thread worlds.
> <
>
> If I understand this correctly, then I'd say that that is what HPX does too. (I usually explain to others that OpenMP creates 'parallel regions', where code operates in tasks, whereas the whole of an HPX application is one enormous parallel region). I presume this is what you mean by 'thread worlds'
Not sure if I understand. Can you point me to some documentation or
examples?

Disclaimer: my knowledge of HPX is limited to a quick glance at the doc.
Feel free to correct my mistakes.

I understood HPX as a library returning futures to calls to asynchronous
functions, somewhat similar to std::async.
In that case, the main region with all the futures would be a thread
world for asynchronous. In huge applications, this does not solve the
problem of organizing thousands of objects within threads.

>>
> The libraries also do not have the same design / tradeoffs. Asynchronous can make use of futures but encourages callbacks and tries to make these as safe as possible. The goal is to be as asynchronous (meaning non-blocking) as possible.
> <
>
> A future .then() or continuation is really just a type of callback too (broadly speaking).

Not really, if I understand correctly
(http://en.cppreference.com/w/cpp/experimental/future/then). The functor
object passed to then() is executed in an unspecified thread of
execution, which makes it hard for the caller to (safely) pass data
which might or might not be valid or relevant at the time the then
functor executes.
I however could not find out whether this also applied to HPX.

This simple example, called within a state machine living within a
thread world will help me show the difference:

post_callback(
     // task running in threadpool
     [](){/* long lasting task */},
     // callback
     [this](boost::asynchronous::expected<void>)
     {
       // if this is called, it is guaranteed that:
       // this executes within the thread context of the calling object
       // the calling object is still alive

       //----> we now decide what to do next
     }
);

As the callback executes within the calling object's thread context, we
can choose at the callback execution time if we still want to call the
code which we would call in the then(), and if we call, we do it with
data relevant at this time, not at the time of the first call.

>>
> Future-based designs do not mix well with state machines' run-to-completion.
> <
>
> Could you elaborate a little on that comment please? I have a had a couple of instances where I'm manipulating 'state' and transitioning from one to another - I would welcome some ideas on how to make this a bit cleaner.

A future.then() returns another future so isn't it just delaying the
fact that I have to decide at some point what to do with the future
object? Do I poll it, get() it or ignore it?
Polling is tedious, ignore usually wrong, and get() means blocking. As a
state machine run-to-completion is supposed to execute in no time, this
is not a good option.
Run-to-completion means: event is sent, transition is executed. Until it
completes, the state machine is in an unstable state. This has to be
kept as short as possible.

>>
> The reason for the non-blocking focus is that I'm using the library at work in an industrial 24/7 application. When working on the production line, blocking is a disaster. If an algorithm goes astray, or simply takes longer than usually, blocking the production line results in huge costs. Crashes due to races also. Asynchronous provides ways to avoid both.
> <
>
> I would say that non-blocking behaviour is one of the central goals of HPX. Continuations are only triggered when futures become ready and therefore blocking is avoided - so I don't think there's any disagreement there! Races are a problem, but a functional style of programming goes a long way to avoiding them.

I agree that HPX likely solves well the race problem, which is a great
achievement.
I feel both libraries solve quite different problems. Asynchronous is
focusing on organizing objects into threads and building everything else
on top of that. In that context, callbacks within these object's thread
contexts make more sense than a fire-and-forget of a future.then();

Which does not mean a fundamental disagreement with HPX, simply a
different focus.

> Thanks for the reply - I'll be going through your repo looking for good ideas (and borrowing them).

I'd love it!
Thanks a lot for the feedback, I now see what things doc is missing
(explanation of thread worlds, reasons for callbacks)

> Cheers
>
> JB
>

Cheers,
Christophe


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk