
On Mar 14, 2007, at 8:01 PM, Peter Dimov wrote:
Howard Hinnant wrote:
What if there existed a:
template <class R>
template <class F>
promise_functor<R, F>
promise<R>::operator()(F f);
I'd actually expect from this syntax to call f and install the result into the promise in one easy step. :-)
That sounds like a thread launch, which indeed ought to be easy. We've got (at least) 4 basic concepts floating around here: * return_value<R> This is a private implementation detail class that nobody ever sees. It is not copyable nor movable. It represents the result of a computation, which can be either normal or exceptional. It has getters and setters for normal and exceptional results. It lives on the heap and various handles share its ownership. * future<R> // return_value getter This forwards a getter request to return_value<R>. The getter may need to wait for a signal from a setter. * promise<R> // return_value setter This is a setter of return_value<R>, signaling any waiting getters. Setting normal or exceptional result is explicit. * functor<R, F> // return_value setter This is a functor that executes a function F and stores the normal or exceptional result in a return_value<R>, possibly via a promise<R>. The result setting is implicit, depending on whether F returns normally, or has an exception propagate out of it. Purposefully (and wisely imho) left out of this mix is what actually executes a setter for return_value<R>. functor<R, F> and promise<R> are simply thin interfaces to setting return_value<R>. But they don't represent asynchronous execution. Thus you can create a function that calls promise<R>::set(r) which is asynchronously executed, say in a thread or a thread_pool. Or you can adapt an existing function by constructing a functor<R, F> with it, and then execute that adapted function in a thread or thread_pool. Either way, the setting of return_value can happen synchronously, in a dedicated thread asynchronously, or be queued in a container of functors (possibly priority sorted) waiting to be processed. Ultimately I think we want to support syntax along the lines of: future<T> t = f( b ); c = g( d ); e = h(t(), c); whereby functors and promises are hidden in relatively low level code, and high level code can just get a future, assume that it is being executed asap, and then join with it later. Perhaps that morphs the above example into: std::thread_pool launch_in_pool; int main() { std::future<T> t = launch_in_pool(std::bind(f, b)); c = g( d ); e = h(t(), c); } -Howard