Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

thread_guard vs scoped_thread

In the book

"C++ Concurrency In Action" by Anthony Williams

you can find the following two snippet of code (I have introduced some slight modifications):

Snippet 1:

class thread_guard
{
    std::thread& t;
    public:
    explicit thread_guard(std::thread& t_): t(t_){}
    ~thread_guard()
    {
        if(t.joinable())
    {
        t.join();
    }
    }
    thread_guard(thread_guard const&)=delete;
    thread_guard& operator=(thread_guard const&)=delete;
};

void my_func()
{
    for(int j = 0; j < 1000; ++j)
    {
        cout << "\n " << j;
    }
}

void f()
{
    std::thread t1(my_func);
    thread_guard g(t1);
    do_something_in_current_thread();
}

int main()
{
    f();
    return 0;
}

Going on you can find

Snippet 2:

class scoped_thread
{
    std::thread t;
    public:
    explicit scoped_thread(std::thread t_):    t(std::move(t_))
    {
        if(!t.joinable())
        throw std::logic_error(“No thread”);
    }
    ~scoped_thread()
    {
        t.join();
    }
    scoped_thread(scoped_thread const&)=delete;
    scoped_thread& operator=(scoped_thread const&)=delete;
};

void my_func()
{
    for(int j = 0; j < 1000; ++j)
    {
        cout << "\n " << j;
    }
}

void f()
{
   scoped_thread st1(thread(my_func));

   thread t2(my_func);
   scoped_thread st2(move(t2));

   do_something_in_current_thread();
}

int main()
{
    f();
    return 0;
}

I'm not sure that I can really appreciate the real difference between these 2 snippets.

The only difference that I can see is that in Snippet 1 the instance of thread_guard does not take ownership of the thread t1 (unlike a scoped_thread object) and so it could be possible call t1.join() but this is not a problem when ~thread_guard() is executed.

So: where is (if exists) the advantage of Snippet 2?

like image 978
openyourmind Avatar asked Jun 07 '19 15:06

openyourmind


People also ask

What happens when you dont join a thread?

If you don't join these threads, you might end up using more resources than there are concurrent tasks, making it harder to measure the load. To be clear, if you don't call join , the thread will complete at some point anyway, it won't leak or anything.

What is a scoped thread?

Tutorial. Scoped Threads are wrappers around a thread that allows the user to state what to do at destruction time. One of the common uses is to join the thread at destruction time so this is the default behavior.


1 Answers

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.

like image 103
Pezo Avatar answered Sep 27 '22 18:09

Pezo