【问题标题】:Thread Building Blocks concurrent_bounded_queue — how do I «close» it?线程构建块 concurrent_bounded_queue — 我如何“关闭”它?
【发布时间】:2013-06-02 10:55:57
【问题描述】:

我正在使用concurrent_bounded_queue Intel TBB 4.1 Update 3 进行生产者和消费者线程之间的通信:

队列类有一个名为abort 的方法,该方法将tbb::user_abort 抛出到阻塞在队列实例的poppush 上的所有线程。两个线程之间的通信可能如下所示:

ConsThread | ProdThread
-----------+-------------
q.pop      |  get new data
(wait)     |  q.push
process    |  get new data
q.pop      |  no more data!
(wait)     |  q.abort
quit       |  quit

不幸的是,即使在这个简单的示例中,我也无法使用它来可靠地关闭队列,因为如果某些消费者在调用 abort 之前没有完成之前的 popped 数据处理,他们将完成迭代并返回阻止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)|

现在我正在使用一个中度恶心的 hack,它产生另一个非分离线程(它加入消费者池线程)并等待它完成,同时不时发送更多 aborts 给后来者:

bool areConsumerThreadsJoinedThankYou = false;
std::thread joiner(Joiner(consumerPool, &areConsumerThreadsJoinedThankYou));

while (!areConsumerThreadsJoinedThankYou) {
    rawQueue.abort();
    MAGIC_MSLEEP(100);
}

class Joiner的实现差不多

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;
}

这当然很丑。有没有更根本的解决方案?

【问题讨论】:

    标签: multithreading queue tbb


    【解决方案1】:

    创建一个指定的“EndOfData”项。如果您知道您有 K 个消费者,则让生产者在完成推送数据项后推送 K“EndOfData”项。让每个消费者在弹出“EndOfData”项目后退出。

    如果事先不知道 K,让生产者推送一个“EndOfData”项。然后让每个弹出“EndOfData”项目的消费者在离开之前推送另一个“EndOfData”项目。在所有消费者完成后,将剩下一个“EndOfData”项,当队列被销毁时,该项将被销毁。

    【讨论】:

    • 好吧,既然这是来自TBB的架构师,我想没有更好的办法:)
    • 感谢您的夸奖。事实上,我是 TBB 的架构师,尽管 Alexey Kukanov 此后担任了 TBB 架构师的角色。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 2011-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多