動作を中断して状況を見たいが、ブレークポイントなどでプログラムそのものを中断すると出力コードも動かなくて困る。デバッグしたい処理をスレッドで動かし、セマフォを使うことで任意の場所で中断・再開できるらしい。
#include <iostream> #include <semaphore> #include <atomic> #include <thread>
class MyBreakPoint { std::binary_semaphore gate{ 0 }; // 許可は最大1に飽和 std::atomic<bool> run_free{ false }; // trueで連続実行 public: // 停止点: run_free=false のときだけ待つ void BreakPoint() { if (run_free.load(std::memory_order_acquire)) return; gate.acquire(); } // 次のBreakPointまで進める void ContinueToNextBreak() { gate.release(); } // 以後ブレーク無視 void RunFree() { run_free.store(true, std::memory_order_release); gate.release(); // 既に待っていれば抜ける } // 以後BreakPointで停止 void PauseAtBreak() { run_free.store(false, std::memory_order_release); // 残っている許可を掃き出し、次回は必ず止まる while (gate.try_acquire()) { /* drain */ } } };
void worker(MyBreakPoint& pauser) { for (int i = 0; i < 100; ++i) { // 処理本体 std::cout << i << std::endl; if (i % 5 == 0) { std::cout << "i % 5 == 0" << std::endl; pauser.BreakPoint(); // ブレークポイント } // 動作を見るための速度調節 std::this_thread::sleep_for(std::chrono::milliseconds(100)); } std::cout << "done" << std::endl; }
int main() { MyBreakPoint poser; std::thread th(worker, std::ref(poser)); // ユーザー入力でデバッグ操作 for (char c; std::cin >> c; ) { if (c == 'c') poser.ContinueToNextBreak();// 次にBreakPointが呼ばれるまで実行 else if (c == 'r') poser.RunFree();// 以後BreakPointを無視 else if (c == 'p') poser.PauseAtBreak();// 以後BreakPointが呼ばれたら止まる } th.join(); }