On Fri, Sep 4, 2015 at 11:56 PM, Vicente J. Botet Escriba
wrote: Hi Giovanni,
boost::future has a lot of design issues. I will welcome and base class from which boost::future can inherit as it is quite difficult to maintain it by myself :(. I'm a little bit skeptical about the approach, but who knows. what are your concerns in particular?
Basically what I would like is to decouple the signalling of a future shared_state, as done by e.g. the promise, from the action to be taken. The intuition is that most efficient implementations of synchronization primitives are based on a fast lock free user space signalling path plus a slow kernel path in case there are waiters. My idea is to decouple the slow path from the actual signalling implementation. The decoupling is done via an interface like this:
struct signalable { virtual void signal() = 0; atomic
next = 0; }; An actual signalable implementation could invoke a continuation (unifying then and wait), signalling a condition variable, an event, a file descriptor, switching to another fiber etc.
The signaler side has something like this:
struct signaler { void signal();
bool try_wait(signalable *); bool try_unwait(signalable*); };
Note this is not virtual. In fact it could simply be a concept. Try_wait attempts to add the signalable to the wait list for the signaler. Failure means that the signaler was signaled in the meantime. try_unwait attempts to remove the signalable from the wait list. Failure also means that the signaler was signaled in the meantime.
The signaler can be implemented lock_free except in the case in which try_unwait is called *and* there are multiple waiters. I believe this case can be handled with a spinlock just for mutual exclusion between unsignalers (try_waiters and signal can still be lock free), but I have yet to implement it
With this interface a future can be implemented without any additional synchronization.
For example the default implementation of 'then' would simply allocate a new shared state for the returned future which inherit from signalable and register it to the shared_state of the previous continuation. The callback is allocated inline in the shared_state. When signal is called, the callback is invoked.
The default wait of course would create a wait object on the stack (or have a thread local one) which also implements the signalable interface (a portable implementation would be based on a condition variable + boolean flat + mutex). A timed wait need to use the try_unwait interface if the clock times out.
Sorry for the rambling, hopefully the idea is a bit clearer.
I have shared my implementation previously. This is the link again:
https://github.com/gpderetta/libtask/blob/master/future.hpp
Note: incomplete, buggy and definitely not production ready. Giovanni, I'm all for adapting Boost.Thread to any global solution to
Le 05/09/15 02:04, Giovanni Piero Deretta a écrit : this problem. What we need first is some one working on it, and showing that we are able to efficiently implement when_all/when_any for some kind of future concept. Then we can try to see how to make boost::future/std::future ...... models of this concept. If you have ideas on how this can work, a POC and time, I propose you to work on it and propose such a library to Boost. I don't believe it is fair to add a link to a ongoing work implementation during the review of a library having a different scope.
Note that boost::future and boost::thread have some interactions (at thead exit family functions) that need to be taken in account
I imagine that can be tricky. Is it much more complex than the thread holding a pointer to the shared state to be made ready on exit?
It is not a question of how complex it can be. It is a matter of public interfaces. We don't have such public interface on the standard and I believe that we need something like that. It is not a good thing that futures and threads be so dependent. The difficulty is defining the interface that makes them (futures/thread) independent without falling to a specific implementation. Thanks for re-rasing these interaction problems, but I believe that these should be handled outside the scope of this review. I suggest you to start a new thread. Vicente