फ्यूचर्स बनाम वादे


135

मैं भविष्य और वादे के बीच अंतर के साथ खुद को भ्रमित कर रहा हूं।

जाहिर है, उनके पास अलग-अलग तरीके और सामान हैं, लेकिन वास्तविक उपयोग मामला क्या है?

क्या यह?:

  • जब मैं कुछ async कार्य प्रबंधित कर रहा हूं, तो मैं "भविष्य में" मूल्य प्राप्त करने के लिए भविष्य का उपयोग करता हूं
  • जब मैं async कार्य कर रहा होता हूं, तो मैं वादे का उपयोग रिटर्न प्रकार के रूप में करता हूं ताकि उपयोगकर्ता को मेरे वादे से भविष्य मिल सके

1
मैंने इस उत्तर में इसके बारे में थोड़ा लिखा ।
केरेके एसबी सेप

1
डुप्लिकेट के संभावित डुप्लिकेट :: वादा?
निकोल बोलस

जवाबों:


163

भविष्य और वादा एक अतुल्यकालिक ऑपरेशन के दो अलग-अलग पक्ष हैं।

std::promise अतुल्यकालिक ऑपरेशन के "निर्माता / लेखक" द्वारा उपयोग किया जाता है।

std::future अतुल्यकालिक ऑपरेशन के "उपभोक्ता / पाठक" द्वारा उपयोग किया जाता है।

इसका कारण इन दो अलग-अलग "इंटरफेस" में अलग-अलग है , "लेखन / सेट" कार्यक्षमता को "उपभोक्ता / पाठक" से छुपाना है

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 का उपयोग करके async :: वादा हो सकता है:

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जाएगा जब थ्रेड समाप्त होने तक वास्तव में ब्लॉक हो जाता है।


3
@taras सुझाव देते हैं कि वापसी std::move(something)बेकार है और यह (N) RVO को भी नुकसान पहुंचाता है। उसका संपादन बदल रहा है।
पोलोकोनिकोव

विज़ुअल स्टूडियो 2015 में कृपया std :: cout << future.get ()। C_str () का उपयोग करें;
डेमियन

6
जो लोग अभी भी भ्रमित हैं, उनके लिए यह उत्तर देखें ।
kawing-chiu

2
यह एक समय निर्माता - उपभोक्ता, IMHO है जो वास्तव में निर्माता - उपभोक्ता पैटर्न नहीं है।
मार्टिन मीसर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.