2012-09-27 96 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)。 –