1

I'm going through "C++ Concurrency in Action" book which shows a following code snippet as a kind of substitute for std::experimental::async

#include <experimental/future>
template<typename Func>
std::experimental::future<decltype(std::declval<Func>()())>
spawn_async(Func&& func){
    std::experimental::promise<decltype(std::declval<Func>()())> p;
    auto res=p.get_future();
    std::thread t(
        [p=std::move(p),f=std::decay_t<Func>(func)]()
            mutable{
            try{
                p.set_value_at_thread_exit(f());
            } catch(...){
                p.set_exception_at_thread_exit(std::current_exception());
            }
    });
    t.detach();
    return res;
}

There is an usage of *_at_thread_exit() functions to handle both happy and exception paths with an emphasis they are required to set the future ready after all thread_local variables have been properly destroyed as opposed to their ordinary counterparts (set_value/set_exception). Why is it so crucial to modify the future's shared stated right after thread_local have been destroyed assuming a thread gets detached (as in the code)?

Any example/crcumstances when this function will lead to program crash or manifest undefined behaviour when set_value or set_exception is used rather than actual calls? There is a bunch of similar questions on stackoverflow but I cannot grasp anything useful from them.

Mati
  • 753
  • 4
  • 20
  • Not sure this is the only possible issue so I don't mark it as a duplicate, but does this answer your question? https://stackoverflow.com/questions/19744250/what-happens-to-a-detached-thread-when-main-exits/27796014#27796014 – Homer512 Aug 27 '22 at 12:55
  • Not really, I've already read this thread and don't get this statement: "[...] because, in general, there will be more code executed after e.g. a notify_all() of a condition variable, in particular the destructors of automatic and thread-local objects". In particular, why is it problematic that more code will be executed afterwards? – Mati Aug 27 '22 at 13:40
  • 1
    It's problematic if the main thread has exited and the detached thread is the only remaining one. You avoid racing the termination of the main thread with the termination of the worker thread. Basically it is a way to ensure that the detached thread can run all its destructors in a well-defined state – Homer512 Aug 27 '22 at 14:09
  • I found your explanation really useful! – Mati Aug 27 '22 at 16:24

0 Answers0