メインスレッドとこのスレッドのみが何もしないマルチスレッドアプリケーションで、まれに heisenbug が発生します。ハイゼンバグなので、なぜこれが起こっているのか理解するのは本当に難しい.
メインスレッドは基本的にループするだけです。ループでは、実行する時間順に並べられたタスクを含む複数の同時優先キューをチェックします。タスクをポップし、それを実行する時が来たかどうかを確認します。時間があれば、TBB のタスク スケジューラにスケジュールするだけです (他のすべてのタスクの親であるルート タスクを使用)。時間がない場合、タスクは優先キューに再度プッシュされます。それは1サイクルです。サイクルの終わりに、メインスレッドは非常に短い時間スリープ状態になりますが、実際にはもっと長くなると予想されますが、実際には問題ではありません。必要でないときにリソースを使いすぎないようにしたいだけです。
文字通り:
static const auto TIME_SCHEDULED_TASKS_SPAWN_FREQUENCY = microseconds(250);
while( !m_task_scheduler.is_exiting() ) // check if the application should exit
{
m_clock_scheduler.spawn_realtime_tasks(); // here we spawn tasks if it's time
this_thread::sleep_for( TIME_SCHEDULED_TASKS_SPAWN_FREQUENCY );
}
m_clock_scheduler.clear_tasks();
m_root_task.wait_for_all();
毎秒「TICK」メッセージを記録する特別なタスクがあります。番組終了まで自動で振替です。ただし、heisenbug が表示されると、「TICK」が消え、アプリケーションが非メイン スレッドで発生する作業以外に何もしていないことがわかります。そのため、メインスレッドのみが触れられているようです。
問題はさまざまな場所、おそらくスケジューリング ロジックから発生する可能性がありますが、スリープ コールを持つ唯一のスレッドでもあります。そのスリープはboost::this_thread::sleep_for()です。
私の質問は次のとおりです。Windows (7 64 ビット) がメイン スレッドが頻繁にスリープしていると見なし、要求されたよりも長い時間スリープするか、確実に終了する必要があると判断する可能性はありますか?
それは不可能だと思いますが、確認したいと思います。これまでのところ、オンライン ドキュメントでこれに関する正確な情報は見つかりませんでした。
アップデート:
バグを体系的に再現できる友人がいます (Windows Vista、Core 2 Duo 上)。私は彼にスリープなしのバージョンと、タスクがキューにプッシュされるたびに condition_variable がメインスレッドを目覚めさせるように condition_variable を使用してメインループを再実装したバージョンを送信しました (ただし、生成の最小時間はまだあります)。
スリープなしのバージョンは動作します (ただし速度は遅くなります)。そのため、実際のソースがわからなくても問題は関連しているようです。
condition_variable を使用するバージョンは動作します - これは、スリープ コールが正しく動作しないことを示していますか?
そのため、明らかにバグを修正しましたが、特定のスリープコールがブロックされる理由はまだわかりません。
アップデート:
これは実際には Boost コードによって引き起こされたバグでした。バグを探して報告したところ、修正されました。以前のバージョンは確認していませんが、Boost 1.55 で修正されています。