简体   繁体   中英

reassignment/move of std::future waits for existing future to complete

The main method below launches two std::async s. The future f in the main method is initially used to hold the future for the first async before being reassigned to the future of the second std::async. Both threads still appear to still complete on schedule which surprised me. Initially I (foolishly?) expected the first thread to be terminated/suspended on the reassignment of the future but was surprised to find it still lingering around.

Based on what I observed today I think I understand that the first async thread becomes detached at the future reassignment. I kept seeing segfaults during my ordeal today and I reckon this was simply the main thread terminating before the orphaned async processes could finish.

////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <future>
#include <thread>
#include <chrono>

#define WAIT_A_MINUTE std::this_thread::sleep_for(std::chrono::seconds(5));

int myBusyFunc() {
    WAIT_A_MINUTE
    std::cout<<"done!"<<std::endl;
    return 71675;
}

std::string futureStatusStr(std::future<int>& f){
    switch (f.wait_for(std::chrono::seconds(0))){
    case std::future_status::ready: return "ready";
    case std::future_status::timeout: return "timeout";
    case std::future_status::deferred: return "deferred";
    default:return "unknown";
    };
}

void printFutureStatus(std::future<int>& f){
    std::cout<<futureStatusStr(f)<<std::endl;
}
/////////////////////////////////////////////////////////////////////////////

int main()
{
    std::future<int> f = std::async(std::launch::async,myBusyFunc);
    printFutureStatus(f);
    f = std::async(std::launch::async,myBusyFunc);  // waits a minute
    printFutureStatus(f);
    f.wait(); // no wait required - ready
    printFutureStatus(f);

    return 0;
}

Additionally, it is noteworthy that the second printFutureStatus(f); statement immediately after the future reassignment doesn't flush immediately. It does appear that the future reassignment causes the main thread to wait. This still surprises me - could anyone offer an explanation?

This behavior is actually documented in std::future::~future . Excerpt from the documentation below:

  • these actions will not block for the shared state to become ready, except that it may block if all of the following are true:

    • the shared state was created by a call to std::async ,
    • the shared state is not yet ready, and
    • this was the last reference to the shared state.

In practice, these actions will block only if the task's launch policy is std::launch::async (see "Effective Modern C++" Item 36), either because that was chosen by the runtime system or because it was specified in the call to std::async .

So, you can see that this result is not unexpected. When you reassign f , the old object is destroyed and in that process the caller becomes blocked.

Taking the above into consideration, if you need to replace the future without blocking, you have a few options:

  1. Use deferred execution policy ( std::launch::deferred )
  2. Store the shared state before replacing: auto g = f.share();
  3. If you want to discard or "abort" the old async call, introduce a mechanism to signal it for early-out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM