4

concurrent_bounded_queueプロデューサー スレッドとコンシューマー スレッド間の通信に Intel TBB 4.1 Update 3 を使用しています。

キュー クラスには、キュー インスタンスをブロックするすべてのスレッドにスローするメソッドが呼び出されますabort。2 つのスレッド間の通信は次のようになります。tbb::user_abortpoppush

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

残念ながら、この単純な例でもキューを確実にシャットダウンするために使用することはできません。一部のコンシューマーがpopへの呼び出しの前に以前にペディングされたデータの処理を完了していない場合abort、それらは反復を終了して でのブロックに戻るため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)|

現在、別の非デタッチ スレッド (コンシューマー プール スレッドに参加) を生成し、それが終了するのを待ってabort、後発者のために時々より多くの sを送信するという、中程度に不快なハックを採用しています。

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

もちろん、これは非常に醜いです。もっと根本的な解決策はありますか?

4

1 に答える 1