C++ 如何使用c++;11 std::thread来实现类似QThread的类?
C++ 如何使用c++;11 std::thread来实现类似QThread的类?,c++,multithreading,c++11,qthread,C++,Multithreading,C++11,Qthread,std::thread不是简单地由类继承,在销毁时不能自动加入,等等 很多陷阱,比如需要使用std::atomic\u bool停止,当使用std::thread作为成员变量来执行成员方法时,不能简单地共享对象的this 使用std::thread实现类似QThread的类有什么好的实践吗 我的目标是一个可继承的线程类,启用start(),detach(),stop()功能 例如,我写了一篇如下: #include <atomic> #include <chrono>
std::thread
不是简单地由类继承,在销毁时不能自动加入,等等
很多陷阱,比如需要使用std::atomic\u bool
停止,当使用std::thread
作为成员变量来执行成员方法时,不能简单地共享对象的this
使用std::thread
实现类似QThread的类有什么好的实践吗
我的目标是一个可继承的线程类,启用
start()
,detach()
,stop()
功能
例如,我写了一篇如下:
#include <atomic>
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <thread>
#include <vector>
struct Thread {
Thread(int id) {
std::atomic_init(&(this->id), id);
std::atomic_init(&(this->m_stop), false);
}
Thread(Thread &&rhs) :
id(),
m_stop(),
m_thread(std::move(rhs.m_thread))
{
std::atomic_init(&(this->id), rhs.id.load());
rhs.id.store(-1);
std::atomic_init(&(this->m_stop), rhs.m_stop.load());
}
virtual ~Thread() {
this->stop();
}
void start() {
this->m_thread = std::move(std::thread(&Thread::work, this));
}
void stop() {
this->m_stop.store(true);
if (this->m_thread.joinable()) {
this->m_thread.join();
}
}
virtual void work() {
while (!(this->m_stop)) {
std::chrono::milliseconds ts(5000);
std::this_thread::sleep_for(ts);
}
}
std::atomic_int id;
std::atomic_bool m_stop;
std::thread m_thread;
};
int main() {
srand(42);
while (true) {
std::vector<Thread> v;
for (int i = 0; i < 10; ++i) {
auto t = Thread(i);
v.push_back(std::move(t));
printf("Start %d\n", i);
v[i].start();
}
printf("Start fin!\n");
int time_sleep = rand() % 2000 + 1000;
std::chrono::milliseconds ts(time_sleep);
std::this_thread::sleep_for(ts);
for (int i = 0; i < 10; ++i) {
printf("Stop %d\n", i);
v[i].stop();
printf("Pop %d\n", i);
v.pop_back();
}
printf("Stop fin!\n");
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
结构线程{
线程(int-id){
std::原子初始化(&(this->id),id);
std::atomic_init(&(this->m_stop),false);
}
螺纹(螺纹和rhs):
id(),
m_stop(),
m_螺纹(标准::移动(rhs.m_螺纹))
{
std::atomic_init(&(this->id),rhs.id.load();
rhs.id.store(-1);
std::atomic_init(&(this->m_stop),rhs.m_stop.load();
}
虚拟线程(){
此->停止();
}
void start(){
this->m_thread=std::move(std::thread(&thread::work,this));
}
无效停止(){
此->m_stop.store(true);
如果(此->m_thread.joinable()){
此->m_thread.join();
}
}
虚空工作(){
而(!(此->m_站)){
标准时间:毫秒ts(5000);
std::this_线程::sleep_for(ts);
}
}
std::原子内部id;
std::原子波停止;
标准:螺纹m_螺纹;
};
int main(){
srand(42);
while(true){
std::向量v;
对于(int i=0;i<10;++i){
自动t=螺纹(i);
v、 推回(标准::移动(t));
printf(“开始%d\n”,i);
v[i].start();
}
printf(“启动fin!\n”);
int time_sleep=rand()%2000+1000;
std::chrono::毫秒ts(睡眠时间);
std::this_线程::sleep_for(ts);
对于(int i=0;i<10;++i){
printf(“停止%d\n”,i);
v[i].stop();
printf(“弹出%d\n”,i);
v、 向后弹出();
}
printf(“停止鳍!\n”);
}
返回0;
}
但是,在
stop0
它死锁之后,或者有时它的内核转储之后,我很难把它正确地处理好。std::thread
是实现线程原语的最低构造块。因此,它没有提供像QThread那样丰富的接口,但与标准库中的同步原语一起,它允许您非常轻松地实现QThread提供的更复杂的行为
您正确地指出,从std::thread
继承是一个坏主意(没有虚拟析构函数是一个致命的缺陷),我认为拥有多态线程类型一开始并不是最聪明的设计,但您可以轻松地将std::thread
封装为任何类的成员(多态或非多态)如果你想的话
加入破坏行动实际上只是一项政策。将std::thread
封装为成员的类可以简单地在其析构函数中调用join
,有效地实现销毁时的自连接。这里不考虑并发性,因为根据定义,对象销毁总是非并发执行的。如果您想在多个(可能同时调用)执行路径之间共享线程的所有权,std::shared_ptr
将为您处理该问题。但即使在这里,析构函数也总是由最后一个放弃其共享的线程非并发执行
像QThread::isInterruptionRequested
这样的东西可以用一个标志来实现,当然,对该标志的访问必须由类同步(使用互斥或使用原子标志)
更改线程的优先级不是由标准指定的,因为并非标准设想的所有平台都允许这样做,但是您可以使用特定于平台的代码自己实现这一点
等等。所有部件都在那里,您只需根据需要组装它们。std::thread
是实现线程原语的最低构建块。因此,它没有提供像QThread那样丰富的接口,但与标准库中的同步原语一起,它允许您非常轻松地实现QThread提供的更复杂的行为
您正确地指出,从std::thread
继承是一个坏主意(没有虚拟析构函数是一个致命的缺陷),我认为拥有多态线程类型一开始并不是最聪明的设计,但您可以轻松地将std::thread
封装为任何类的成员(多态或非多态)如果你想的话
加入破坏行动实际上只是一项政策。将std::thread
封装为成员的类可以简单地在其析构函数中调用join
,有效地实现销毁时的自连接。这里不考虑并发性,因为根据定义,对象销毁总是非并发执行的。如果您想在多个(可能同时调用)执行路径之间共享线程的所有权,std::shared_ptr
将为您处理该问题。但即使在这里,析构函数也总是由最后一个放弃其共享的线程非并发执行
像QThread::isInterruptionRequested
这样的东西可以用一个标志来实现,当然,对该标志的访问必须由类同步(使用互斥或使用原子标志)
更改线程的优先级不是由标准指定的,因为并非标准设想的所有平台都允许这样做,但是您可以使用特定于平台的代码自己实现这一点
等等。所有部件都在那里,您只需根据需要组装即可。en