2012-09-27 11 views
88

Ich verwechsle mich mit dem Unterschied zwischen einer Zukunft und einem Versprechen.Futures vs. Promises

Offensichtlich haben sie verschiedene Methoden und Zeug, aber was ist der tatsächliche Anwendungsfall?

Ist es ?:

  • , wenn ich einige async Aufgabe bin Verwaltung, ich Zukunft verwenden Sie den Wert „in Zukunft“
  • zu bekommen, wenn ich die Asynchron Aufgabe bin, benutze ich versprechen als die Rückgabetyp, um dem Benutzer eine Zukunft von meinem Versprechen zu ermöglichen
+0

Ich schrieb ein wenig darüber [in dieser Antwort] (http://stackoverflow.com/a/12335206/596781). –

+1

möglich duplicate von [Was ist std :: versprechen?] (Http://stackoverflow.com/questions/11004273/what-is-stdpromise) –

Antwort

118

Zukunft und Versprechen sind die zwei getrennten Seiten eines asynchronen Vorgangs.

std::promise wird vom "Producer/Writer" des asynchronen Betriebs verwendet.

std::future wird vom "Consumer/Reader" des asynchronen Betriebs verwendet.

Der Grund, warum es in diese zwei separaten "Schnittstellen" getrennt ist, ist verstecken die "schreiben/setzen" -Funktionalität aus dem "Consumer/Reader".

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

Eine (unvollständige) Art und Weise std zu implementieren :: async std :: Versprechen sein könnte:

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

Mit std::packaged_task, die einen Helfer (dh es hat im Grunde, was wir oben taten) ist um std::promise könnten Sie die folgende tun, die vollständigere und möglicherweise schneller ist:

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

Beachten Sie, dass diese von std::async etwas anders wo die zurückgegebene std::future wird bei der Zerstörung tatsächlich blockiert, bis der Thread beendet ist.

+1

@taras schlägt vor, dass die Rückgabe von 'std :: move (etwas)' nutzlos ist und es tut auch weh (N) RVO. Seine Bearbeitung rückgängig machen. –

+0

In Visual Studio 2015 verwenden Sie bitte std :: cout << future.get(). C_str(); – Damian

+3

Für diejenigen, die immer noch verwirrt sind, siehe [diese Antwort] (http://stackoverflow.com/questions/11004273/what-is-stdpromise/12335206#12335206). –