首页 > 解决方案 > 用于创建类生成线程的多个实例的 C++ 线程模型

问题描述

抽象的:

我正在设计一个类 ( Inner),它产生 2 个线程——一个生产者和一个消费者。在一种用法中有一个实例,而在另一种情况下有多个实例。

在 Standalone 中,我需要两个线程来继续写入/读取消息。但是,如果有多个实例,我需要代码来生成两个线程,但继续创建下一个类(以生成更多线程)。

我的问题是尝试将这两种情况与正确使用std::thread::join()和结合起来std::thread::detach()

代码详情:

该类Inner产生一个线程来接收和排队消息,以及第二个线程来读取队列并将消息发送到拥有的类Inner

template<Owner>
class Inner
{
    Inner(Owner& owner) : _owner(owner)
    {
        // Spawn thread to receive packets and put on queue
        // Spawn thread to read from queue
    }

    void receiveMessage(const Message& msg)
    {
        // Ommitted locks etc for simplicty
        _queue.push(msg);
    }

    void readFromQueue()
    {
        // Ommitted loop, locks etc for simplicty
        _owner.receiveMessage(msg);
    }

    Owner& _owner;
    std::queue<Message> _queue;
};

有两种可能的所有者类别SingleInner

class OneInner
{
    OneInner()
    {
        _inner = std::make_unique<Inner>();
    }

    void receiveMessage(const Message& msg){//Code ommitted}

    std::unique_ptr<Inner> _inner;
};

第二个上下文有多个实例:

class MultipleInners
{
    MultipleInners()
    {
        // Need to create multiple instances of Inner, each with Inner's two threads running
    }

    void receiveMessage(const Message& msg){//Code ommitted}

    std::vector<std::unique_ptr<Inner>> _inners;
};

我不确定如何允许Inner生成 2 个线程,让它们继续运行,但在OneInner代码中等待并且在MultipleInners代码中继续创建下一个Inner.

或者是否有更好的方法来实现这一目标?

标签: c++multithreadingarchitecturepthreads

解决方案


对于类的每个实例都需要一个资源,并且其生命周期与匹配实例的生命周期相同,最好将其表示为成员变量。

所以只需让线程成员变量Inner在构造时启动,并在销毁时加入:

template<Owner>
class Inner
{
    Inner(Owner& owner) 
      : _owner(owner)
      , _recv_thread([this](){readFromQueue();}),
      , _read_thread([this](){receiveLoop();}),
    {
    }

    ~Inner() {
      _recv_thread.join();
      _read_thread.join();
    }

    void receiveLoop() {
      while(...) {
        //etc...
        receiveMessage(msg);
      }
    }

    void receiveMessage(const Message& msg)
    {
        // Ommitted locks etc for simplicty
        _queue.push(msg);
    }

    void readFromQueue()
    {
        // Ommitted loop, locks etc for simplicty
        _owner.receiveMessage(msg);
    }


    Owner& _owner;
    std::queue<Message> _queue;
    
    // Make sure these are the last members, so that _owner and _queue 
    // are constructed already when the threads start
    std::thread _recv_thread;
    std::thread _read_thread;

};

推荐阅读