"永远"阻止线程的最简单便携式方法是什么?



我有一个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后台线程将永远不会自己退出。Foo实例析构函数修改m_stopFlag只能停止,如果出现任何问题,任何产生的异常都将导致进程中止。

我想写一个main()的版本,就像上面的版本一样,它永远不会(或者至少不会,直到类似信号的东西)到达main()的末尾,从而结束我的Foo后台线程。

Foo在我的控制之下,但除非必要,否则我宁愿不改变它。

您可能会在条件变量上等待一段时间。条件变量从不发出信号。由于虚假查找,您仍然需要while循环,并且您需要一个残留互斥。额外的好处是,当你确实需要突破等待循环时,如何做到这一点是显而易见的。如果抽象可用,等待信号量也会起作用。

也就是说,在任何实际情况下,都会出现复杂情况。首先,线程抽象可能在"可移植"的定义中,也可能不在。其次,在某些环境中,主线程有责任运行事件循环。因此,这将不是完全可移植的。在基于POSIX的系统上,我可能只使用sigwait

最新更新