我希望我的类产生两个线程,这些线程将循环运行并与所有者类进行交互。当我最初使用单线程的类(一个原子标志,一个互斥锁等)时,这很容易。但是随着对第二个线程的需求增加,我正在考虑一些更优雅的解决方案,该解决方案将封装线程及其实用程序。例如:ThreadWrapper类,可以在所有者类中实例化。
到目前为止,我提出了以下建议,但是我不确定这是否是正确的方法:
class ThreadWrapper
{
public:
ThreadWrapper()
: m_threadShouldRun(false)
, m_threadRunning(false)
{
}
ThreadWrapper(std::function<void()> fn)
: m_threadShouldRun(true)
, m_threadRunning(false)
, m_threadFunction(fn)
{
m_threadPointer = std::make_shared<std::thread>(std::thread([&] { this->threadLoop(); }));
}
virtual ~ThreadWrapper()
{
if (m_threadRunning)
m_threadShouldRun = false;
m_threadPointer->join();
m_threadPointer = nullptr;
}
private:
void threadLoop()
{
m_threadRunning = true;
while(m_threadShouldRun)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
m_threadFunction();
}
m_threadRunning = false;
}
std::function<void()> m_threadFunction = []{};
std::shared_ptr<std::thread> m_threadPointer;
std::atomic<bool> m_threadShouldRun;
std::atomic<bool> m_threadRunning;
};
用法(固定):
class Foo
{
Foo()
: t1(std::function<void()>(std::bind(&Foo::internalLoop1, this)))
, t2(std::function<void()>(std::bind(&Foo::internalLoop2, this)))
{
}
ThreadWrapper t1;
ThreadWrapper t2;
std::mutex mtx;
void internalLoop1()
{
// looped task
{
std::scoped_lock lock(mtx);
// write'n'read data to tx/rx queues
}
}
void internalLoop2()
{
// looped task
{
std::scoped_lock lock(mtx);
// process the rx queue
}
}
};
这有点类似于我发现的here包装器。 缺点是需要将睡眠时间传递给ThreadWrapper对象。
这是正确的方法吗?还是应该使用基类并仅继承虚拟方法呢?如下图所示。
来源:https://www.codeproject.com/Articles/18383/A-thread-wrapper-class
理想情况下,我想在这里使用模板,但是两个ThreadWrapper之间唯一的“不同”部分是单个方法,而是建议我继承/函数指针。还是我在这里错了?
编辑:动机。在C#中,可以执行以下操作:var t1 = new Thread(() => internalLoop1());
最后,我要在我的主要班级照顾这样的一员。其他ThreadWrapper类将负责线程安全管理。因此,如果要产生多个线程,则很容易复制。