concurrent_bounded_queue
プロデューサー スレッドとコンシューマー スレッド間の通信に Intel TBB 4.1 Update 3 を使用しています。
キュー クラスには、キュー インスタンスをブロックするすべてのスレッドにスローするメソッドが呼び出されますabort
。2 つのスレッド間の通信は次のようになります。tbb::user_abort
pop
push
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;
}
もちろん、これは非常に醜いです。もっと根本的な解決策はありますか?