thread_guard vs scoped_thread thread_guard vs scoped_thread multithreading multithreading

thread_guard vs scoped_thread


Both types are meant to block on destruction (e.g. scope exit) until a thread finishes. The difference is in the ownership of the thread object.

thread_guard doesn't own the thread itself; there may be more than one thread_guard waiting on the same thread. This also means that the thread object must be alive as long as any thread_guard refers to it. If the referenced thread has already been joined when a thread_guard object is destroyed, it won't block or produce an error (as opposed to just calling join on a thread that is not joinable).

scoped_thread, on the other hand, takes ownership of the thread instance, and therefore also controls its lifetime. You would use it whenever you want to own the thread you want to wait on, e.g. as a data member.

Ultimately, which one you use is a question of semantics: do you want to wait on a thread someone else owns (then you also have to make sure there are no lifetime issues), or do you want a thread object that blocks when it gets destroyed, without you having to join it first.


In terms of functionality these both implementation are capable to server the purpose, the only difference i can see in these two implementation is, Snippet 2 can accept both lvalue(glvalue) and rvalue(prvalue) but Snippet 1 can't accept rvalue(prvalue) as constructor argument. For example consider following code,

std::thread getThread(){    return std::thread([](){ std::cout<< __PRETTY_FUNCTION__<< std::endl;});}int main( int , char *[]){    thread_guard g( getThread());    return 0;}

Now if you compile this code, compile will give following error,

 error: cannot bind non-const lvalue reference of type ‘std::thread&’ to an rvalue of type ‘std::remove_reference<std::thread&>::type’ {aka ‘std::thread’}     explicit thread_guard(std::thread _t): t(std::move( _t)){ std::cout<< __PRETTY_FUNCTION__<< std::endl;}

But snippet 2 implementation will work fine.