2

我有一个foo返回future. foo将注册一个回调,该回调将在foo返回后调用。

future<int> foo() {
    promise<int> p;
    future<int> ret(p.get_future());
    thread(bind([] (promise<int> &&p) {
        this_thread::sleep_for(chrono::seconds(3));
        p.set_value(10);
    }, move(p))).detach();
    return move(ret);
}

int main()
{
    auto f = foo();
    cout << f.get() << endl;
    return 0;
}

但似乎std::bind将右值引用作为左值引用转发,因此无法成功编译。有什么办法可以解决吗?


我必须编写一个丑陋的类来移动promise对象:

template<typename T>
class promise_forward {
    promise<T> promise_;

public:
    promise_forward(promise<T> &&p) : 
        promise_(move(p)) {}

    promise_forward(promise_forward<T> &&other) : 
        promise_(move(other.promise_)) {}

    operator promise<T> () {
        return move(promise_);
    }
};

future<int> foo() {
    promise<int> p;
    future<int> ret(p.get_future());
    thread(bind([] (promise<int> &&p) {
        this_thread::sleep_for(chrono::seconds(3));
        p.set_value(10);
    }, promise_forward<int>(move(p)))).detach();
    return ret;
}

int main()
{
    auto f = foo();
    cout << f.get() << endl;
    return 0;
}
4

1 回答 1

1

基本上,你不需要std::bind在这里(好吧,我相信是这样=))。这是一个最简单的异步任务启动器的快速草稿。它几乎和你的一样,但是更通用一点:它可以接受任何函数对象并且它的侵入性更小:函数对象对承诺或线程一无所知。

可能有错误(我很确定他们是)。而且,当然,它离std::async实现还很远(通常不仅仅是线程启动器,但理想情况下,它有一个巨大的线程管理后端)。

#include <thread>
#include <future>
#include <iostream>
#include <chrono>


template< class Function, class... Args>
std::future<typename std::result_of<Function(Args...)>::type> my_async(Function && f, Args && ... args)
{
    typedef typename std::result_of<Function(Args...)>::type ret_type;

    std::promise<ret_type> p;

    auto fut = p.get_future();


    // lambda in separate variable, just to improve readability 
    auto l = [](Function && f, Args && ... args, std::promise<ret_type> && p)
    {
        p.set_value(f(args...));
    };

    std::thread th(l, std::move(f), std::move(args...), std::move(p));

    th.detach();

    return std::move(fut);

}

int wannaRunAsync(int i)
{
    return i;
};

int main()
{

    auto fut = my_async(&wannaRunAsync, 42);

    auto fut2 = my_async([](int i) -> int { return i; }, 42);

    std::cout << fut.get() << std::endl;
    std::cout << fut2.get() << std::endl;

    std::cin.get();

    return 0;
}

我能够使用 g++-4.8clang++编译和运行它,但是使用 msvc 2012 和 2013 预览版它甚至无法编译(可能是由于错误)。

我根本没有测试过这段代码,所以要小心=)希望它有所帮助。

于 2013-09-04T19:44:30.290 回答