实现future :: then()等效于c ++ 11中的异步执行

Rom*_*lak 29 c++ concurrency asynchronous c++11

then()Herb Sutter的演讲中有一些关于函数实现的问题.此函数用于链接异步操作,参数f是一个操作的未来,参数w是此操作的"工作"(lambda).

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

申请的一个例子是:

    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;
    });
Run Code Online (Sandbox Code Playgroud)

主线程产生任务但不等待它们中的任何一个完成.

首先,future<T>没有复制构造函数.这意味着,shared_future<T>除非我们将调用更改async()为将未来移动到lambda ,否则建议的实现只能用于.这个问题提出了一种方法,但似乎太复杂了.我重新实现了这个功能,我想知道我的代码是否正确或是否遗漏了一些东西......

其次,传递给then()函数的未来可能是void这样,我们实际上需要2个实现then(),对吧?一个用于期货回归T,一个用于期货回归void.

最后,如果body内的lambda then()没有return语句,那么我们实际上可以返回值吗?如果没有return语句,那么返回future<void>吧?

我试图解决上述问题,这就是我想出的.这是对的吗?

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));
}
Run Code Online (Sandbox Code Playgroud)

bar*_*ney 5

这种 .then() 方法的问题在于,您同时产生了 2 个线程(成本很高),而其中的第二个线程会在其 future.get/wait 上阻塞(当然,如果第一个线程运行的时间足够长)所以,最好使用工作队列,序列化作业执行顺序(并回收现有线程)。只需寻找一个好的线程池模式实现


ela*_*dan 4

为了简化界面,我将void问题“隐藏”在实现中,类似于 Herb 对他的concurrent<T>实现所做的事情。不要使用 2 个then实现,而是声明一个具有 2 个实现的辅助函数get_work_done

template <typename T, typename Work>
auto get_work_done(future<T> &f, Work &w)-> decltype(w(f.get()))
{return w(f.get());}

template <typename Work>
auto get_work_done(future<void> &f, Work &w)-> decltype(w())
{f.wait(); return w();}
Run Code Online (Sandbox Code Playgroud)

然后让模板参数检测处理剩下的事情:

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 get_work_done(f,w); }, move(f), move(w));
}
Run Code Online (Sandbox Code Playgroud)