gpt4 book ai didi

c++ - 如何使用 c++11 std::thread 实现类 QThread 类?

转载 作者:行者123 更新时间:2023-11-28 01:51:58 25 4
gpt4 key购买 nike

std::thread 不能简单地被类继承,不能在销毁时自动加入等等。

很多陷阱,比如需要使用 std::atomic_bool 来停止,在使用 std::thread 时不能简单地共享对象的 this作为成员变量来执行成员方法。

使用 std::thread 实现类 QThread 有什么好的做法吗?


我的目标是一个可继承的 Thread 类,启用 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;
}

但我很难把它弄好,就在 Stop 0 之后它陷入僵局,或者有时它发生核心转储。

最佳答案

std::thread 旨在作为实现线程原语的最低构建 block 。因此,它不像 QThread 那样提供丰富的接口(interface),但与标准库中的同步原语一起,它允许您非常轻松地实现更复杂的行为,如 QThread 提供的行为。

你正确地注意到从 std::thread 继承是一个坏主意(没有虚拟析构函数是一个死的赠品)而且我认为拥有多态 Thread 类型并不是最聪明的设计放在首位,但如果需要,您可以轻松地将 std::thread 封装为任何类(多态或非多态)的成员。

加入破坏实际上只是一种政策。将 std::thread 封装为成员的类可以简单地在其析构函数中调用 join,有效地实现销毁时的自连接。并发在这里无关紧要,因为根据定义,对象销毁总是非并发执行的。如果您想在多个(可能同时调用的)执行路径之间共享一个线程的所有权,std::shared_ptr 将为您处理。但即使在这里,析构函数也总是由最后一个放弃其 shared_ptr 的剩余线程非并发执行。

QThread::isInterruptionRequested 之类的东西可以用单个标志实现,访问它当然必须由类同步(使用互斥锁或使用原子标志)。

标准未指定更改线程的优先级,因为并非标准设想的所有平台都允许这样做,但您可以使用 native_handle使用特定于平台的代码自行实现。

等等。所有零件都在那里,您只需根据需要组装它们即可。

关于c++ - 如何使用 c++11 std::thread 实现类 QThread 类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42670837/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com