Replacing std::async with own version but where should std::promise live? Replacing std::async with own version but where should std::promise live? multithreading multithreading

Replacing std::async with own version but where should std::promise live?


Here is one solution:

future<string> myasync(){    auto prms = make_shared<promise<string>> ();    future<string> fut = prms->get_future();    thread th([=](){        try {            string val = thFun();            // ...            prms->set_value(val);        } catch(...) {            prms->set_exception(current_exception());        }     });    th.detach();    return fut;}

Allocate promise on the heap, and then pass-by-value [=] a shared_ptr to it through to the lambda.


You need to move the promise into the new thread. Andrew Tomazos's answer does it by creating a std::promise with shared ownership, so that both threads can own the promise, and when the current one returns from the current scope only the new thread owns the promise, i.e. the ownership has been transferred. But std::promise is movable so it should be possible to move it directly into the new thread, except that the "obvious" solution of capturing it doesn't work because lambda's can't capture by move, only by copy (or by reference, which wouldn't work as you'd get a dangling reference.)

However, std::thread supports passing rvalue objects to the new thread's start function. so you can declare the lambda to take a std::promise argument by value, i.e. pass the promise to the lambda rather than capturing it, and then move the promise into one of the arguments of the std::thread e.g

std::future<std::string> myasync() {    std::promise<std::string> prms;    std::future<std::string> fut = prms.get_future();    std::thread th([&](std::promise<std::string> p){        try {            std::string val = thFun();            p.set_value(val);        } catch(...) {            p.set_exception(std::current_exception());        }     }, std::move(prms));    th.detach();    return fut;}

This move the promise into the std::thread object, which then moves it (in the context of the new thread) into the lambda's parameter p.