Vadeli İşlemler ve Vaatler


135

Kendimi bir gelecek ile söz arasındaki farkla karıştırıyorum.

Açıkçası, farklı yöntemleri ve malzemeleri var, ancak gerçek kullanım durumu nedir?

Bu mu?:

  • eşzamansız bir görevi yönetirken, "gelecekte" değeri elde etmek için geleceği kullanırım
  • Eşzamansız görev olduğumda, kullanıcının sözümden bir gelecek elde etmesini sağlamak için dönüş türü olarak söz veriyorum

1
Bu cevapta bunun hakkında biraz yazdım .
Kerrek SB

1
olası yinelenen std nedir :: sözü?
Nicol Bolas

Yanıtlar:


163

Future ve Promise, zaman uyumsuz bir işlemin iki ayrı yüzüdür.

std::promise zaman uyumsuz işlemin "üreticisi / yazarı" tarafından kullanılır.

std::future zaman uyumsuz işlemin "tüketici / okuyucusu" tarafından kullanılır.

Bu iki ayrı "arayüze" ayrılmasının nedeni , "yaz / ayarla" işlevini "tüketici / okuyucudan" gizlemektir .

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 :: promise kullanarak std :: async uygulamasının (eksik) bir yolu şunlar olabilir:

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

Kullanılması std::packaged_tasketrafında bir yardımcı (temelde yukarıda ne yaptıklarını yapar bunu yani) hangi edilir std::promisemuhtemelen daha hızlı daha eksiksiz ve olduğu aşağıdakileri yapabilirsiniz:

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

Bunun, yıkıldığında std::asyncdöndürülen std::futureöğenin iş parçacığı bitene kadar engellendiği yerden biraz farklı olduğuna dikkat edin.


3
@taras, geri dönmenin std::move(something)yararsız olduğunu ve ayrıca (N) RVO'ya zarar verdiğini öne sürüyor . Düzenlemesini geri alıyorum.
polkovnikov.ph

Visual Studio 2015'te lütfen std :: cout << future.get (). C_str ();
Damian

6
Hala kafası karışmış olanlar için bu yanıta bakın .
kawing-chiu

2
Bu tek seferlik bir üretici - tüketici, IMHO, aslında üretici - tüketici modeli değildir.
Martin Meeser
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.