スポンサーリンク

C++、セマフォを使ってブレークポイントのようなものを設置

動作を中断して状況を見たいが、ブレークポイントなどでプログラムそのものを中断すると出力コードも動かなくて困る。デバッグしたい処理をスレッドで動かし、セマフォを使うことで任意の場所で中断・再開できるらしい。

#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();
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: