Thread Building Blocks concurrent_bounded_queue — how do I «close» it?

有些话、适合烂在心里 提交于 2020-01-04 02:28:12

问题


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 popped 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 aborts 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!