On 12/04/2016 04:15 PM, Hartmut Kaiser wrote:
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
Hartmut, can we leave HPX aside and talk about the library discussed here?
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.
Not at all! The first examples are using futures to show that the library supports futures and as transition to the other, more powerful parts of the library. The future-based continuations are also provided for cases where no other possibility is available (external libraries returning futures).
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.
It implies blocking the current thread of execution, at least std::future. I'm not talking about HPX ones, as I do not know the library and would prefer to comment only asynchronous and std. Coming back to my other favorite subject, if a state machine is waiting on a get(), its run to completion is incorrect and it cannot react to events.
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?
This is what I understand from reading the description of std experimental. If future::then is executed by a threadpool thread, it is not done by the single thread world and a race risk is given in order to not execute the then part. Am I missing something?
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.
In my experience, not everything is functional and not only futures encourage value semantics. By using a threadpool, one is automatically encouraged to do so: move into the pool, move back from it. Asynchronous simply takes another way to these goals. It aims at race-free programming and hides threads just to a certain point: know where they are and how many, do not access them directly. I suppose, some will prefer HPX or std::async style, others Asynchronous. There are probably many ways to the same goal. Regards, Christophe
Regards Hartmut --------------- http://boost-spirit.com http://stellar.cct.lsu.edu
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost