8

無限ループで動作するオブジェクトがあります。オブジェクトをインスタンス化し、メソッドmain()を呼び出しますrun()。スレッドを使用したくないので、オブジェクトの実行を停止するためのソリューションが必要です。以下に私が思いついたものを示します。

struct Foo
{
    void run()
    {
        running = 1;
        while (running) 
            do_something_useful();

        std::cout << "Execution stopped." << std::endl;
    }

    bool running;

    void catch_signal(int signal)
    {
        std::cout << "Caught signal " << signal << std::endl;
        if( signal == SIGTERM ) 
            running = false;
    }

};

ご覧のとおり、非同期でシグナルを送信する必要があります。したがって、シグナルハンドラとを使用しsigactionます。以下でmain私は使用することを想像することができます。

int main(int argc, char** argv)
{
    Foo foo;
    struct sigaction sigIntHandler;

    boost::function< void (int) > f;
    f = std::bind1st(
      std::mem_fun(&Foo::catch_signal), &foo);
    f(5);  // this call works

    sigIntHandler.sa_handler = f;           // compiler complains, "cannot assign ..."
    sigemptyset(&sigIntHandler.sa_mask);
    sigIntHandler.sa_flags = 0;
    sigaction(SIGTERM, &sigIntHandler, NULL);
    s.run();

}

私が今期待すること:プログラムは私が送信するまで実行SIGTERMされ、それがキャッチされ、オブジェクトが反復を停止してメインに戻ります。

私は今2つの質問があります:

(a)「Compilercomplains」とマークされた行が表示されるコードでは、メッセージは次のようになります。

boost::function<void(int)> cannot be converted to __sighandler_t {aka void (*)(int)}

これを機能させるには何を変更する必要がありますか?いくつかの例でシグナルハンドラが取得する関数のfように、と思います。void f(int)

(b)「あの男は何をしているの?」と思っている人のために:この種のことをもっとうまく解決する方法について何かアドバイスはありますか?

4

2 に答える 2

8
  • これを機能させるには何を変更する必要がありますか?いくつかの例でシグナルハンドラが取得する関数のように、fはvoid f(int)のようなものだと思います。

コンパイラは型について文句を言うので、型のオブジェクトではなく、関数ポインタを渡す必要がありますboost::function<void(int)>。このタイプのグローバル変数を作成し、このオブジェクトを呼び出す関数を追加すると、次のように機能します。

boost::function<void(int)> myCb;
void CallCb( int value )
{
  myCb(value);
}

int main(int argc, char** argv)
{
    Foo foo;
    struct sigaction sigIntHandler;

    myCb = std::bind1st(
      std::mem_fun(&Foo::catch_signal), &foo);
    f(5);  // this call works

    sigIntHandler.sa_handler = CallCb;
    sigemptyset(&sigIntHandler.sa_mask);
    sigIntHandler.sa_flags = 0;
    sigaction(SIGTERM, &sigIntHandler, NULL);
    s.run();

}
  • このようなことをもっとうまく解決する方法について何かアドバイスはありますか?

あまり。アイデアは大丈夫​​です。代わりにc++11ラムダだけにします

于 2012-10-12T11:11:21.033 に答える
3

シグナルハンドラーで移植できることはほとんどありません。基本的に、タイプが。であるオブジェクトに値を格納できますsig_atomic_t。たとえば、への挿入coutは機能する必要はありません。C ++ 11を使用している場合は、アトミック型または明示的なフェンスを使用してもう少し実行できますが、標準ライブラリへの他の呼び出しは、適切な処理を行う必要はありません。

つまり、あなたができることは、関数(フリー関数または静的メンバー関数のいずれか)を作成することです(ただし、ここではC ++リンケージに微妙な問題があります:正式には静的メンバー関数は機能しませんが、実際にはそれは常にそうします))それはメンバー関数を呼び出します、そしてそれは順番にに設定runningfalseます(あなたがのタイプを変更したと仮定しrunningsig_atomic_t)。

于 2012-10-12T12:35:41.887 に答える