Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

implementing future::then() equivalent for asynchronous execution in c++11

I have a few questions about the implementation of the function then() in Herb Sutter's talk. This function is used to chain asynchronous operations, the parameter f is a future from one operation and the parameter w is the 'work' for this operation (lambda).

template <typename Fut, typename Work> auto then(Fut f, Work w) -> future<decltype(w(f.get()))> {     return async([=]{ w(f.get()); }); } 

An example of application would be:

    std::future<int> f = std::async([]{         std::this_thread::sleep_for(std::chrono::microseconds(200));         return 10;     });      auto f2 = then(std::move(f), [](int i){         return 2 * i;     }); 

The main thread spawns the tasks but does not wait for any of them to finish.

Firstly, future<T> does not have a copy constructor. This means, that the suggested implementation can be only used with shared_future<T> unless we change the call to async() to move the future into the lambda. This SO question suggested a way of doing it but it seems too complicated. I re-implemented the function and I am wondering whether my code is correct or whether I missed something...

Secondly, the future that is passed to the then() function might be void so we actually need 2 implementations of then(), right? One for futures returning T and one for futures returning void.

Lastly, should the lambda inside the body of then() not have a return statement so that we can actually return the value back? Without the return statement, then returns future<void>, right?

I tried to address the above points and this is what I came up with. Is it correct?

template <typename T, typename Work> auto then(future<T> f, Work w) -> future<decltype(w(f.get()))> {     return async([](future<T> f, Work w)                       { return w(f.get()); }, move(f), move(w)); }  template <typename Work> auto then(future<void> f, Work w) -> future<decltype(w())> {     return async([](future<void> f, Work w)                       { f.wait(); return w(); }, move(f), move(w)); } 
like image 784
Roman Kutlak Avatar asked Jan 23 '13 21:01

Roman Kutlak


People also ask

What is std :: async?

The function template async runs the function f asynchronously (potentially in a separate thread which might be a part of a thread pool) and returns a std::future that will eventually hold the result of that function call. 1) Behaves as if (2) is called with policy being std::launch::async | std::launch::deferred.

What is future class in C++?

A future is an object that can retrieve a value from some provider object or function, properly synchronizing this access if in different threads. "Valid" futures are future objects associated to a shared state, and are constructed by calling one of the following functions: async. promise::get_future.

Does STD async use thread pool?

How does std::launch::async Work in Different Implementations? For now, we know that if no policy is specified, then std::async launches a callable function in a separate thread. However, the C++ standard does not specify whether the thread is a new one or reused from a thread pool.


1 Answers

The problem with this approach to .then() is that you spawn 2 threads (that is costly) simultaneously, and second of them would block on its future.get/wait (if the first one would run long enough, of course) So, its better to use the work queue, to serialize the jobs execution order (and re-cycle the existing threads). Just look for a good Thread pool pattern implementation

like image 153
barney Avatar answered Sep 22 '22 07:09

barney