用于创建 class 个生成线程的多个实例的 C++ 线程模型
C++ threading model for creating multiple instances of class spawning threads
摘要:
我正在设计一个生成 2 个线程的 class (Inner
) - 一个生产者和一个消费者。在一种用法中有一个实例,在另一种情况下有多个实例。
在 Standalone 中,我需要两个线程来继续 writing/reading 消息。但是,如果有多个实例,我需要生成两个线程的代码,但继续创建下一个 class(生成更多线程)。
我的问题是尝试将这两种情况与 std::thread::join()
和 std::thread::detach()
的正确用法相结合。
代码详情:
class Inner
生成一个线程来接收和排队消息,以及第二个线程来读取队列并将消息发送到拥有 Inner
的 class。
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;
};
有两个可能的所有者 classes,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
.
或者是否有更好的方法来实现这一目标?
如果资源的每个实例都需要一个 class,并且其生命周期与匹配实例的生命周期相同,则最好将其表示为成员变量。
所以只需要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;
};
摘要:
我正在设计一个生成 2 个线程的 class (Inner
) - 一个生产者和一个消费者。在一种用法中有一个实例,在另一种情况下有多个实例。
在 Standalone 中,我需要两个线程来继续 writing/reading 消息。但是,如果有多个实例,我需要生成两个线程的代码,但继续创建下一个 class(生成更多线程)。
我的问题是尝试将这两种情况与 std::thread::join()
和 std::thread::detach()
的正确用法相结合。
代码详情:
class Inner
生成一个线程来接收和排队消息,以及第二个线程来读取队列并将消息发送到拥有 Inner
的 class。
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;
};
有两个可能的所有者 classes,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
.
或者是否有更好的方法来实现这一目标?
如果资源的每个实例都需要一个 class,并且其生命周期与匹配实例的生命周期相同,则最好将其表示为成员变量。
所以只需要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;
};