2012-09-27 95 views
88

我对未来和承诺之间的差异感到困惑。期货与承诺

显然,他们有不同的方法和东西,但实际的用例是什么?

是不是?:

  • 当我管理的一些异步任务,我用未来的“未来”来获取值
  • 当我异步任务,我用的承诺作为返回类型以允许用户从我的承诺中获得未来
+0

我写了一个关于这个[在这个答案](http://stackoverflow.com/a/12335206/596781)。 –

+1

[什么是std :: promise?](http://stackoverflow.com/questions/11004273/what-is-stdpromise) –

回答

118

Future和Promise是异步操作的两个独立方面。

std::promise被异步操作的“生产者/写入者”使用。

std::future被异步操作的“消费者/读者”使用。

它被分成这两个单独的“接口”的原因是hide“消费者/阅读器”的“写入/设置”功能。

auto promise = std::promise<std::string>(); 

auto producer = std::thread([&] 
{ 
    promise.set_value("Hello World"); 
}); 

auto future = promise.get_future(); 

auto consumer = std::thread([&] 
{ 
    std::cout << future.get(); 
}); 

producer.join(); 
consumer.join(); 

一个(不完全)的方式来实现的std ::异步使用std ::承诺可能是:

template<typename F> 
auto async(F&& func) -> std::future<decltype(func())> 
{ 
    typedef decltype(func()) result_type; 

    auto promise = std::promise<result_type>(); 
    auto future = promise.get_future(); 

    std::thread(std::bind([=](std::promise<result_type>& promise) 
    { 
     try 
     { 
      promise.set_value(func()); // Note: Will not work with std::promise<void>. Needs some meta-template programming which is out of scope for this question. 
     } 
     catch(...) 
     { 
      promise.set_exception(std::current_exception()); 
     } 
    }, std::move(promise))).detach(); 

    return std::move(future); 
} 

使用std::packaged_task这是一个辅助(即它基本上做什么我们做以上)各地std::promise你可以做的是更完整,更可能更快如下:

template<typename F> 
auto async(F&& func) -> std::future<decltype(func())> 
{ 
    auto task = std::packaged_task<decltype(func())()>(std::forward<F>(func)); 
    auto future = task.get_future(); 

    std::thread(std::move(task)).detach(); 

    return std::move(future); 
} 

注意,这是从std::async略有不同其中返回的std::future将在被销毁时实际阻塞,直到线程完成。

+1

@taras表明返回'std :: move(something)'是无用的,它也会伤害(N)RVO。恢复他的编辑。 –

+0

在Visual Studio 2015中,请使用std :: cout << future.get()。c_str(); – Damian

+3

对于那些仍然困惑,请参阅[这个答案](http://stackoverflow.com/questions/11004273/what-is-stdpromise/12335206#12335206)。 –