包装std :: thread以作为类成员重用

时间:2018-10-15 17:35:24

标签: c++ multithreading c++11 c++14

我希望我的类产生两个线程,这些线程将循环运行并与所有者类进行交互。当我最初使用单线程的类(一个原子标志,一个互斥锁等)时,这很容易。但是随着对第二个线程的需求增加,我正在考虑一些更优雅的解决方案,该解决方案将封装线程及其实用程序。例如: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对象。

这是正确的方法吗?还是应该使用基类并仅继承虚拟方法呢?如下图所示。 Thread model from codeproj.

来源:https://www.codeproject.com/Articles/18383/A-thread-wrapper-class

理想情况下,我想在这里使用模板,但是两个ThreadWrapper之间唯一的“不同”部分是单个方法,而是建议我继承/函数指针。还是我在这里错了?

编辑:动机。在C#中,可以执行以下操作:var t1 = new Thread(() => internalLoop1());最后,我要在我的主要班级照顾这样的一员。其他ThreadWrapper类将负责线程安全管理。因此,如果要产生多个线程,则很容易复制。

0 个答案:

没有答案