Reputation: 11016
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
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
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
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