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? <<
For you and any others reading this, the main hpx docs are here http://stellar-group.github.io/hpx/docs/html/ but there is useful additional material in the form of tutorial slides https://stellar-group.github.io/tutorials/#1 and they link to a number of examples - though the main hpx repo has an examples directory with many more of them.
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. << Yes, I suppose that the whole application would be a single thread world using that analogy. Objects are not 'bound' to a particular thread, they can be accessed freely from any thread and the user is responsible for protecting them - or preferably writing functional-like code to avoid collisions etc.
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. << In HPX there are launch policies that can be used to control thread execution, the one that would come closest to what you are looking for would be future<thing> = hpx::async(do_something_interesting()).then(hpx::launch::sync, do_another_interesting_thing()); This tells the .then() continuation to execute the next function in the same context as the thread that completes the initial future. Note that launch::policies control certain aspects of 'how' a thread should be launched, but executors control where (and are a powerful abstraction used extensively throughout HPX)
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. <<
In general yes, there needs to be a .get() at the end of a chain of futures - but fortunately, you can just launch tasks with continuations and 'throw away' the final future - and never call get(). When each task completes, it will trigger it's continuation, and if nobody is 'using' the final value returned from a chain of futures, it will just clean itself up on completion. I didn't quite understand the state machine explanation - but I'll continue looking through the boost.asynchronous material until I am happier. yours JB