问题
I am using concurrent_bounded_queue
Intel TBB 4.1 Update 3 for communication between producer and consumer threads:
- concurrent_queue
- concurrent_bounded_queue
The queue class has a method called abort
which throws tbb::user_abort
to all threads which block on pop
and push
of the queue instance. The communication between two threads may look like this:
ConsThread | ProdThread
-----------+-------------
q.pop | get new data
(wait) | q.push
process | get new data
q.pop | no more data!
(wait) | q.abort
quit | quit
Unfortunately, I cannot use it to reliably shut down the queue even in this simple example, because if some of the consumers are not done processing previously pop
ped data before the call to abort
, they will finish the iteration and return to blocking on pop
:
ConsThread | ProdThread
-----------+-------------
q.pop | get new data
(wait) | q.push
process | get new data
process | no more data!
process | q.abort
process | quit
process |
q.pop |
(wait) |
(wait) |
(wait) |
(so lonely)|
Right now I am employing a moderately disgusting hack that spawns another non-detached thread (which joins the consumer pool threads) and waits for it to finish while sending more abort
s from time to time for the late comers:
bool areConsumerThreadsJoinedThankYou = false;
std::thread joiner(Joiner(consumerPool, &areConsumerThreadsJoinedThankYou));
while (!areConsumerThreadsJoinedThankYou) {
rawQueue.abort();
MAGIC_MSLEEP(100);
}
class Joiner
's implementation is pretty much
void Joiner::operator()(void)
{
for (auto it = this->m_threadPool.begin();
it < this->m_threadPool.end();
it++)
(*it)->join();
this->m_done = true;
*(this->m_flag) = true;
}
This of course is very ugly. Is there a more fundamental solution?
回答1:
Create a designated "EndOfData" item. If you know you have K consumers, have the producer push K "EndOfData" items after it is done pushing data items. Have each consumer quit after it pops a "EndOfData" item.
If K is not known in advance, have the producer push a single "EndOfData" item. Then have each consumer who pops an "EndOfData" item push another "EndOfData" item before leaving. After all consumers are done, there will be a single "EndOfData" item remaining, which will be destroyed when the queue is destroyed.
来源:https://stackoverflow.com/questions/16961990/thread-building-blocks-concurrent-bounded-queue-how-do-i-close-it