Luca
Luca

Reputation: 11016

Notify caller that a thread has finished

I am trying to use the multithreading features in the C++11 standard library and have the following situation envisioned.

I have a parent class which maintains a queue of thread. So something like:

std::queue<MyMTObject *>  _my_threads;

The class MyMTObject contains the std::thread object. The queue has a fixed size of 5 and the class initially starts with the queue being full.

As I have jobs to process I launch threads and I remove them from the queue. What I would like is to get a notification when the job is finished along with the pointer to the MyMTObject, so that I can reinsert them into the queue and make them available again.

I have basically 2 questions:

1: Is this a sound idea? I know I have not specified specifics but broadly speaking. I will, of course, control all access to the queue with a mutex.

2: Is there a way to implement this notification mechanism without using external libraries like Qt or boost.

For duplicates, I did look on the site but could not find anything that was suitable to manage a collection of threads.

Upvotes: 1

Views: 3220

Answers (3)

Jason
Jason

Reputation: 3917

I'm not sure if I need to mention this, but std::thread objects can't be re-used. Generally, the only reason you keep a std::thread reference is to std::thread::join the thread. If you don't plan to join the thread later (e.g. dispatch to threads and wait for completion), it's generally advised to std::thread::detach it.

If you're trying to keep threads for a thread pool, it's probably easier to have each thread block on the std::queue and pull objects from the queue to work on. This is relatively easy to implement using a std::mutex and a std::condition_variable. It generally gives good throughput, but to get finer control over scheduling you can do things like keep a seperate std::queue for each thread.

Detaching the threads and creating a work queue also has the added benefit that it avoids redundantly requesting the operating system create new threads which adds overhead and increases overall resource usage.

Upvotes: 2

meshlet
meshlet

Reputation: 1507

You could try to deploy some version of Reactor pattern I think. So, you could start one additional control thread that cleans after these workers. Now, you create a ThreadSafeQueue that will be used to communicate events from worker threads to control thread. This queue should be implemented in such a way that you can select on it and wait for any activity on the other end (some thread terminates and calls queue.push for example).

All in all I think it's quite elegant solution. I does add an overhead of an additional thread, but this thread will be mostly sleeping and waking up only once a while to clean up after the worker.

Upvotes: 2

SergeyA
SergeyA

Reputation: 62613

There is no elegant way to do this in Posix, and C++ threading model is almost a thin wrapper on Posix.

You can join a specific thread (one at a time), or you can wait on futures - again, one future at a time.

The best you can do to avoid looping is to employ a conditional variable, and make all threads singal on it (as well as indicating which one just exited by setting some sort of per-thread flag) just before they are about to exit. The 'reaper' would notice the signal and check the flags.

The issue is that this solution requires thread cooperation. But I know not of any better.

Upvotes: 0

Related Questions