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它被捕获并将导致我的对象停止迭代并返回到 main。

我现在有两个问题:

(a) 在代码中,您会看到标有“编译器抱怨”的行,消息类似于

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),就像信号处理程序在某些示例中获得的函数一样。

编译器会抱怨类型,因此您需要传递函数指针,而不是 type 的对象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 lambda

于 2012-10-12T11:11:21.033 回答
3

您可以在信号处理程序中进行可移植的操作很少。基本上,您可以将值存储在类型为 的对象中sig_atomic_t。例如,插入cout不必工作。如果你有 C++11,你可以做更多的事情,使用原子类型或显式栅栏,但是对标准库的任何其他调用都不需要做任何明智的事情。

因此,尽管如此,您可以做的是编写一个函数(自由函数或静态成员函数(但这里有一个与 C++ 链接有关的微妙问题:正式静态成员函数不起作用,但实际上它总是这样做))调用成员函数,该函数又设置runningfalse(假设您已将类型更改runningsig_atomic_t)。

于 2012-10-12T12:35:41.887 回答