user500944
user500944

Reputation:

Managing multiple concurrent threads

I'm writing a multi-threaded program in C++ using C++11 threading library.

I have the following requirements:

  1. Main thread listens to some type of events, and fires off a new thread for each new event
  2. When program termination is requested, new thread creation is blocked and we wait for the old threads to finish

I have the option to store the threads in some container, for example, a list. Before exit, all threads in the container are join()-ed. However, since STL containers are not thread-safe, additional synchronization is needed when adding a new thread and removing a finished thread from the container. The interaction between the main thread and the child threads becomes a little more complicated in this case. Should the child thread remove itself from the container? If not, how does it let the main thread know when it's time to remove? etc.

Another way I see is to have an atomic int which is incremented by the main thread when a child thread is created, and decremented by the child thread right before its termination (threads will be detach()-ed after creation, so I won't have to manage any std::thread objects). Before exiting, we just wait for the atomic integer to become 0 in a simple loop. This solution looks better to me because there are less moving parts and no locking (at least as long as the target platform has a lock-free implementation of std::atomic<int>).

So, my question is, which of the above methods would you prefer?

Upvotes: 2

Views: 1280

Answers (1)

jxh
jxh

Reputation: 70502

Using the thread counter would be my choice, combined with a condition wait. The last thread exiting should signal the condition variable to wake up the waiter.

// the waiter
{
    std::lock_guard<std::mutex> g(threads_lock);
    while (threads > 0) {
        threads_cond.wait(threads_lock);
    }
}
//...

// the threads that are exiting
if (--threads == 0) {
    std::lock_guard<std::mutex> g(threads_lock);
    threads_cond.notify_one();
}

This is assuming that threads is std::atomic, of course.

Upvotes: 1

Related Questions