什么是最简单的永久阻止线程的可移植方式?

时间:2017-10-28 00:21:07

标签: c++ portability

我有这个类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在我的控制之下,但除非有必要,否则我宁愿不改变它。

1 个答案:

答案 0 :(得分:1)

在条件变量上等待一段时间就像你正在寻找的那样。条件变量永远不会发出信号。由于虚假查找,您仍然需要while循环,并且您需要一个残留的互斥锁。作为奖励,当你确实需要打破等待循环时,很明显该怎么做。如果可以获得抽象,那么等待信号量也会起作用。

那就是说,在任何实际情况下,都有并发症。首先,线程抽象可能是也可能不在你的“便携式”的定义范围内。&#34;其次,在某些环境中,主线程具有诸如运行事件循环之类的职责。所以这不是完全可移植的。在基于POSIX的系统上,我可能只使用sigwait