在 C++11 中实现 future::then() 等价于异步执行

2021-12-14 00:00:00 asynchronous concurrency c++ c++11

我对 then() 的实现有几个问题Beyond-2012-Herb-Sutter-Concurrency-and-Parallelism" rel="noreferrer">Herb Sutter 的演讲.此函数用于链接异步操作,参数 f 是一个操作的未来,参数 w 是此操作的工作"(lambda).>

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()); });
}

应用示例如下:

    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.

首先,future 没有复制构造函数.这意味着,建议的实现只能与 shared_future 一起使用,除非我们更改对 async() 的调用以将未来移动到 lambda 中.这个问题提出了一种方法它但它似乎太复杂了.我重新实现了这个函数,我想知道我的代码是否正确或者我是否遗漏了什么......

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...

其次,传递给 then() 函数的 future 可能是 void 所以我们实际上需要 then() 的 2 个实现, 对?一种用于返回 T 的期货,一种用于返回 void 的期货.

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.

最后,then() 主体内的 lambda 是否应该没有 return 语句,以便我们可以实际返回值?没有return语句,则返回future,对吗?

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));
}

推荐答案

这种 .then() 方法的问题在于,您同时生成 2 个线程(代价高昂),而其中的第二个线程会阻塞它的未来.获取/等待(当然,如果第一个运行时间足够长)因此,最好使用工作队列来序列化作业执行顺序(并回收现有线程).只需要寻找一个好的线程池模式实现

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

相关文章