C ++ - 退出主

时间:2017-01-20 14:11:08

标签: c++ multithreading

在我的main函数中,有一些对象在后台工作,直到调用析构函数,如下面的代码片段所示:

#include <iostream>

class MyBackground {
public:
    MyBackground()
    {
        m_workerThread = std::thread(&MyBackground::work, this);
    }
    ~MyBackground()
    {
        g_exit = true;
        workerThread.join();
    }

private:
    void work()
    {
        while(!m_exit);
    }

private:
    std::atomic<bool> m_exit{false};
    std::thread m_workerThread;
};


int main(int argc, char* argv[])
{
    MyBackground object;

    // here ther's some async background work
    return EXIT_SUCCESS;

    // ~MyBackground -> here threads are stopped
}

我需要一种阻止main的方法,直到出现一些外部信号。我的第一次尝试是这样的:

#include <csignal>
#include <iostream>
#include <thread>

using namespace std

atomic<bool> g_Exit{false};

void signalExit(int)
{
    g_Exit = true;  
}

int main(int argc, char* argv[])
{
    signal(SIGINT, signalExit);
    signal(SIGTERM, signalExit);

    MyBackground object;

    while (!g_Exit)
        this_thread::sleep_for(chrono::seconds{1});

    // here ther's some async background work
    return EXIT_SUCCESS;

    // ~MyBackground -> here threads are stopped
}

但我不确定这是否合适。我认为最好使用condition_variables,如下面的代码段:

#include <csignal>
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

using namespace std

bool g_exitFlag = false;
condition_variable g_exitCondition;
mutex g_exitMutex;

using Lock = unique_lock<mutex>;

void signalExit(int)
{
    Lock lock{g_exitMutex};
    g_exitFlag = true;
    g_exitCondition.notify_one();
}

int main(int argc, char* argv[])
{
    signal(SIGINT, signalExit);
    signal(SIGTERM, signalExit);

    MyBackground object;

    Lock lock{g_exitMutex};
    g_exitCondition.wait(lock, [](){return g_exitFlag;});

    // here ther's some async background work
    return EXIT_SUCCESS;

    // ~MyBackground -> here threads are stopped
}

哪种最佳实施方式是正确的。他们是对的吗?我不是多线程编程的“专家”。

2 个答案:

答案 0 :(得分:4)

为什么不是一个稍微不同的设计,你的后台工作线程不会被MyBackground类创建和销毁,但是线程是在main函数中创建的?然后main函数可以在它退出之前简单地调用线程上的join,它将阻塞直到后台线程完成。

这样的东西
class MyBackground {
public:
    void work()
    {
        while(!m_exit)
        {
            // Do background work
        }
    }

private:
    std::atomic<bool> m_exit{false};
};

int main()
{
    MyBackground background;
    std::thread background_thread(&MyBackground::work, background);

    // Do foreground work

    background.join();  // Wait for background to exit

    // Implicit return
}

另一个解决方案,如果线程在main函数返回时应该继续,则是detach线程。然后它将独立于主线程工作,并且该过程实际上不会退出,直到线程退出。

请注意,这需要main函数不仅返回或exit,因为这将结束包括终止所有线程的进程。相反,你需要退出“主”线程。不幸的是,使用标准C ++线程接口是不可能的,但您必须使用平台本机函数。例如,在POSIX系统(如macOS和Linux)上,您使用pthread_exit

答案 1 :(得分:0)

你可以简单地在main()中使用std :: weak_ptr来检查强引用计数是否为nil来终止。将唯一的强引用指针传递给其他线程,以使main()能够平滑退出。使用std :: conditon_variable来避免关闭等待condition_variable的线程,以减少轮询期间的CPU使用率,以检查weak_ptr是否过期。

void worker_thread(std::shared_ptr<int>& pulse)
{
    // do something
    std::this_thread::sleep_for(std::chrono::seconds(2));

    pulse.reset(); // reset to terminate main() too from any other threads
  }

void main()
{
    std::shared_ptr<int> pulse = std::make_shared<int>(1);
    std::weak_ptr<int> weak_pulse(pulse);

    std::thread([&](){ worker_thread(pulse); }).detach();

    while (auto strong = weak_pulse.lock())
        std::this_thread::sleep_for(std::chrono::milliseconds(100));

}