我正在尝试实现多线程设计,并且需要一些关于线程同步的帮助。
我有两个类,A类和B类。我将解释使用伪代码 A类在main函数中创建。
class A
{
public:
A();
~A();
void tick();
void addEntity();
private:
std::list<entity> entityList;
B* _b;
};
B类如下:
class B
{
public:
B();
~B();
void createSimulation();
void startSimulation();
void registerCallbacks(SimEngine& sim);
void entityCreatedCallback();
boost::signal<void()> signalEntityCreated;
private:
simEngine* sim;
};
A类实现有点像:
A::A()
{
_b = new B();
_b->signalEntityCreated.connect(boost::bind(&A::AddEntity, this));
_b->createSimulation();
}
A::~A()
{
}
void A::tick()
{
entity ent = entityList.pop_front();
//process the entity
}
void A::addEntity(entity ent)
{
entityList.push_back(entity);
}
B类实现有点像:
B::B()
{
}
B::~B()
{
}
B::registerCallback(SimEngine& sim)
{
sim.connect("ENTITY_CREATED", entityCreatedCallback);
}
void B::createSimulation()
{
boost::thread sim_thread(boost::bind(&B::startSimulation, this));
}
void B::startSimulation()
{
sim = new SimEngine();
registerCallback(sim);
sim->start();
}
void B::entityCreatedCallback(simEngine& sim)
{
signalEntityCreated(sim.lastEntity);
}
所以,主要思想是A类创建B类,反过来B类启动一个模拟线程。在开始模拟之前,它会通过模拟注册一些回调函数。当某些状态在模拟中发生变化(即创建的实体)时,会调用这些回调函数。
类a使用boost信号槽机制将类B中的信号(signalEntityCreated)与A类中的本地成员函数连接起来。 在B类中,回调调用信号来触发类A中的成员函数调用。在这种情况下,addEntity,它将新条目添加到std :: list。
A类的tick函数在每一帧中都有一个滴答,需要处理addEntity函数添加的任何实体。
现在,我需要正确地同步这个生成和消费实体机制。 A类在主线程中运行,它绑定到渲染线程,因此它不能等待互斥(长时间),否则渲染性能会降低。
我的观察, 当模拟在不同的线程中运行时,所有回调都属于该线程。当使用boost :: signal调用成员函数时,成员函数也在模拟线程中运行。但是,处理(内部勾选)需要在主线程中运行。
任何建议?
答案 0 :(得分:0)
您只想创建一个从渲染事件循环中轮询的消息队列。
此外,您可以模拟模拟和/或渲染器(A
)遵循活动对象模式¹。
请注意,当跨越线程边界传递事件消息时,您也希望传递实体,否则会出现竞争条件(在处理事件之前已创建多个实体)。
¹见例如 - https://en.wikipedia.org/wiki/Active_object - http://www.drdobbs.com/parallel/prefer-using-active-objects-instead-of-n/225700095 - - https://rosettacode.org/wiki/Active_object#C.2B.2B实际上是一个很好的例子