Boost logo

Boost :

Subject: Re: [boost] Asynchronous library now in Boost Library Incubator
From: Hartmut Kaiser (hartmut.kaiser_at_[hidden])
Date: 2016-12-04 10:15:30


> > 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.

HPX uses futures as explicit means to express dependencies between tasks
which allows for asynchronous execution without barriers. Surely, at some
point you need to call get() on the top-most future representing the whole
execution tree, but this is usually not an issue as most (if not all)
applications have natural synchronization points imposed by their
implemented logic. These future objects are a very useful construct allowing
to express various kind of asynchrony in an application. But I'm sure you
agree to that as more than half of the documentation of Boost.Asynchronous
explains concepts based on using futures as a concept.

> > 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.

Using futures, even if you have to call future::get() does not imply
blocking. It implies possible suspension, which is a completely different
beast. Calling future::get() on one task does not 'block' the kernel-thread
running the task as it is now free to run other tasks.

> > 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();

Why do you think future::then() is fire& forget?

Future::then is a means of turning a future into a callback, while the
opposite can be achieved for instance by using a packaged task. So I'd say
both concepts are equivalent in terms of provided functionality.

The benefit of a future based approach (in my experience) is that it leads
to a very functional style of programming, while encouraging value
semantics. Both things naturally support race-free programming... The other
benefit is that futures very much hide the notion of threads altogether,
thus exposing higher level abstractions freeing the programmer's mind from
tracking thousands (or more) execution states at the same time.

Regards Hartmut
---------------
http://boost-spirit.com
http://stellar.cct.lsu.edu


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