我有一个对象,在无尽的循环中做一些工作。 main()
实例化对象并调用run()
方法。 由于我不想使用线程,我需要一个解决scheme,使我的对象停止运行。 下面你看看我想出了什么。
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; } };
如你所见,我需要asynchronous发送一个信号。 因此,我使用了一个信号处理程序和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
,并将导致我的对象停止迭代,并返回到主。
我现在有两个问题:
(a)在代码中你看到一行标有“Compiler complains”的行,这个消息就像
boost::function<void(int)> cannot be converted to __sighandler_t {aka void (*)(int)}
我需要改变什么来完成这项工作? 我认为f
就像void f(int)
一样,就像信号处理函数在一些例子中得到的函数一样。
(b)对于那些怀疑“那个人在干什么?”的人:你有什么build议可以更好的解决这个问题吗?
- 我需要改变什么来完成这项工作? 我认为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 lambda而已
在信号处理程序中,可以轻松地做的事情非常少。 基本上,您可以将值存储在类型为sig_atomic_t
的对象中。 插入cout
,例如,不必工作。 如果你有C ++ 11,你可以使用原子类型或明确的屏蔽来做更多的事情,但是对标准库的任何其他调用并不需要做任何明智的事情。
所以说,你可以做的是编写一个函数(一个自由函数或者一个静态成员函数)(但是在C ++连接中存在一个微妙的问题:静态成员函数在形式上是行不通的,但是在实践中它总是)),它会调用成员函数,然后将running
设置为false
(假设您已将running
类型更改为sig_atomic_t
)。