我有这个类Foo,这样当你创建它的一个实例时,它会在构造函数中启动一个后台线程,后台线程会运行,直到在对象实例上调用析构函数(它设置一个标志来告诉后台线程退出)然后等待后台线程完成。
所以,我想编写一个无限期运行后台线程的小程序
int main(int argc, char[][] argv)
{
Foo foo(argc, argv);
block_forever(); // How do I implement this portably?
return 0;
}
制作像ctrl-c / a这样的信号以使block_forever
返回将是一个很好的奖励(但一般来说我可以杀死这个过程)
Foo可以建模为
class Foo
{
public:
Foo() : m_stopFlag(false)
{
m_thread = StartThread(&ThreadFn, this);
if (!m_thread) throw ...;
}
~Foo()
{
m_stopFlag = true;
JoinThread(m_thread);
}
private:
void* ThreadFn(void* threadParam)
{
Foo& foo(*static_cast<Foo*>(threadParam);
try
{
while (!foo.m_stopFlag)
{
DoSomethingInteresting();
SleepFiveSeconds();
}
return NULL;
}
catch (...)
{
abort();
}
}
volatile bool m_stopFlag;
THREAD_HANDLE m_thread;
};
因此,Foo后台线程永远不会自行退出。它可以仅由修改m_stopFlag
的Foo实例析构函数停止,如果出现任何错误,任何结果异常都将导致进程中止。
我想编写一个main()
的版本,就像上面的版本一样,永远不会(或者至少在信号之前没有)到达main()
的末尾,从而结束我的Foo后台线程
Foo在我的控制之下,但除非有必要,否则我宁愿不改变它。
答案 0 :(得分:1)
在条件变量上等待一段时间就像你正在寻找的那样。条件变量永远不会发出信号。由于虚假查找,您仍然需要while循环,并且您需要一个残留的互斥锁。作为奖励,当你确实需要打破等待循环时,很明显该怎么做。如果可以获得抽象,那么等待信号量也会起作用。
那就是说,在任何实际情况下,都有并发症。首先,线程抽象可能是也可能不在你的“便携式”的定义范围内。&#34;其次,在某些环境中,主线程具有诸如运行事件循环之类的职责。所以这不是完全可移植的。在基于POSIX的系统上,我可能只使用sigwait
。