Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 包装std::thread以作为类成员重用_C++_Multithreading_C++11_C++14 - Fatal编程技术网

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

C++ 包装std::thread以作为类成员重用,c++,multithreading,c++11,c++14,C++,Multithreading,C++11,C++14,我希望我的类产生两个线程,它们将在循环中运行并与所有者类交互。这很容易,当我的类最初使用单线程时:一个原子标志、一个互斥等。但是随着对第二个线程的需求增加,我正在考虑一些更优雅的解决方案,它将封装线程及其实用程序。例如:ThreadWrapper类,可以在所有者类中实例化 到目前为止,我提出了以下建议,但我不确定这是否正确: class ThreadWrapper { public: ThreadWrapper() : m_threadShouldRun(false)

我希望我的类产生两个线程,它们将在循环中运行并与所有者类交互。这很容易,当我的类最初使用单线程时:一个原子标志、一个互斥等。但是随着对第二个线程的需求增加,我正在考虑一些更优雅的解决方案,它将封装线程及其实用程序。例如: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;
};
类线程包装器
{
公众:
ThreadWrapper()
:m_threadshouldlrun(false)
,m_threadRunning(假)
{
}
螺纹包装器(标准::函数fn)
:m_threadshouldlrun(true)
,m_threadRunning(假)
,m_螺纹功能(fn)
{
m_threadPointer=std::make_shared(std::thread([&]{this->threadLoop();}));
}
虚拟~ThreadWrapper()
{
如果(m_threadRunning)
m_threadShouldRun=false;
m_threadPointer->join();
m_threadPointer=nullptr;
}
私人:
void threadLoop()
{
m_threadRunning=真;
while(m_threadshouldlrun)
{
std::this_线程::sleep_for(std::chrono::毫秒(100));
m_threadFunction();
}
m_threadRunning=假;
}
std::函数m_threadFunction=[]{};
std::共享的线程指针;
std::原子m_线程应运行;
std::原子m_线程运行;
};
用法(固定):

class-Foo
{
Foo()
:t1(std::function(std::bind(&Foo::internalLoop1,this)))
,t2(std::function(std::bind(&Foo::internalLoop2,this)))
{
}
螺纹包装t1;
线状包装物t2;
std::互斥mtx;
void internalLoop1()
{
//循环任务
{
标准:范围锁定(mtx);
//向发送/接收队列写入和读取数据
}
}
void internalLoop2()
{
//循环任务
{
标准:范围锁定(mtx);
//处理接收队列
}
}
};
这有点像我发现的包装。 缺点是睡眠周期需要传递给ThreadWrapper对象

这是正确的方法吗?或者它应该用基类来完成,而只是继承虚拟方法?如下图所示。

资料来源:

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


编辑:动机。在C#中,可以执行以下操作:
vart1=newthread(()=>internalLoop1())最后,我在我的主课上处理这样一行程序。其中另一个ThreadWrapper类负责线程安全管理。因此,如果要生成多个线程,那么很容易复制。

我很难想象
std::shared\u ptr
是正确使用的场景。你真的希望你的包装是可复制的并且共享
std::thread
对象吗?那么其他成员的这些新实例用于什么呢?每个标志都有两个实例、两个函数对象和一个使用一组这些成员的线程。如果原件被销毁,则捕获的
this
将悬空。似乎
std::unique\u ptr
会更好。但在这一点上,您也可以直接使用
std::thread
成员来代替。您有一个busylop,它做一些事情,然后休眠,然后循环。远远少于0.1%的线程代码需要一个busylop,并且需要充分证明它的合理性。我同意@FrançoisAndrieux。对我来说更像是个XY问题。你能更详细地解释一下你最终想要实现/优化什么吗?
这->internalLoop1
是胡说八道。代码的其余部分有很多拼写错误。请尽可能在解释问题时发布编译代码。不要过早地概括代码…实际上,您的解决方案很少可用,因为大多数问题都需要特定的解决方案。例如,您可能需要在特定点启动线程。在正确编写的代码中,几乎不需要有延迟的循环,而是希望等待某个事件。
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
        }
    }
};