我有一个程序,可以在其中启动多个长时间运行的线程(例如REST-API)。对于准备好的信号(例如SIGHUP
),我希望能够干净地关闭所有线程(通过等待它们退出)。下面是thispointer article中的一些代码,这些代码说明了如何执行此操作的好主意
#include <thread>
#include <iostream>
#include <assert.h>
#include <chrono>
#include <future>
void threadFunction(std::future<void> futureObj)
{
std::cout << "Thread Start" << std::endl;
while (futureObj.wait_for(std::chrono::milliseconds(1)) ==
std::future_status::timeout)
{
std::cout << "Doing Some Work" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
std::cout << "Thread End" << std::endl;
}
int main()
{
// Create a std::promise object
std::promise<void> exitSignal;
//Fetch std::future object associated with promise
std::future<void> futureObj = exitSignal.get_future();
// Starting Thread & move the future object in lambda function by reference
std::thread th(&threadFunction, std::move(futureObj));
//Wait for 10 sec
std::this_thread::sleep_for(std::chrono::seconds(10));
std::cout << "Asking Thread to Stop" << std::endl;
//Set the value in promise
exitSignal.set_value();
//Wait for thread to join
th.join();
std::cout << "Exiting Main Function" << std::endl;
return 0;
}
但是,正如人们可能已经注意到的那样,此概念有一个严重的缺点:exitSignal
必须在调用th.join()
之前发出。
在要收听信号的情况下,例如使用signal(SIGHUP, callback)
,这当然是不切实际的。
我的问题是:关闭多个线程是否有更好的概念?我将如何处理它们?我认为使用promise
并不是一个坏主意,我只是还没有找到解决问题的方法。
答案 0 :(得分:0)
您可以在std :: condition_variable上使用std :: notify_all_at_thread_exit()。
这是一个示例:
#include <mutex>
#include <thread>
#include <condition_variable>
#include <cassert>
#include <string>
std::mutex m;
std::condition_variable cv;
bool ready = false;
std::string result; // some arbitrary type
void thread_func()
{
thread_local std::string thread_local_data = "42";
std::unique_lock<std::mutex> lk(m);
// assign a value to result using thread_local data
result = thread_local_data;
ready = true;
std::notify_all_at_thread_exit(cv, std::move(lk));
} // 1. destroy thread_locals;
// 2. unlock mutex;
// 3. notify cv.
int main()
{
std::thread t(thread_func);
t.detach();
// do other work
// ...
// wait for the detached thread
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [] { return ready; });
// result is ready and thread_local destructors have finished, no UB
assert(result == "42");
}