I am currently integrating an entity component system, as seen here, with a physics engine and a graphics engine. This was all fine until recently deciding that the physics should be running in its own thread. (Thanks Glenn Fiedler!)
As it is now I am simply locking a mutex shared by all subsystems when accessing components.
Snippet from the physics loop:
lock_guard<mutex> lock( m_EntMutex );
entitymap::iterator it;
for ( it = m_Ents.begin(); it != m_Ents.end(); ++it )
{
// Get physics component from entity
// This is guaranteed to work ( component must exist for it to present in the map )
shared_ptr<comp_phys> phys( static_cast<comp_phys*>( it->second->getComponent( COMP_PHYS ).lock().get() ) );
// Get resulting Box2D vector
b2Vec2 vec = phys->getBody()->GetPosition();
// Get position component from entity
// Same as above, but this is the component shared with the graphics subsystem
shared_ptr<comp_pos> pos( static_cast<comp_pos*>( it->second->getComponent( COMP_POS ).lock().get() ) );
// Update position component from Box2D vector
pos->setPosition( vec.x, vec.y, 0 );
}
Snippet from graphics loop:
lock_guard<mutex> lock( m_EntMutex );
entitymap::iterator it;
for ( it = m_Ents.begin(); it != m_Ents.end(); ++it )
{
// Get position component from entity
// This is shared with the physics subsystem
shared_ptr<comp_pos> pos( static_cast<comp_pos*>( it->second->getComponent( COMP_POS ).lock().get() ) );
// Get position from position component
doubleVec3 vec = p->getPosition();
// Get graphics component from entity
shared_ptr<comp_gfx> gfx( static_cast<comp_gfx*>( it->second->getComponent( COMP_GFX ).lock().get() ) );
// Update graphics component from position component
gfx->getObject()->getParentSceneNode()->setPosition( float(vec.x), float(vec.y), float(vec.z) );
}
This is obviously a very naïve implementation, so I tried making the individual components have their own mutexes. It seemed the logical performance choice, but then the physics results (as queried through the position component) wouldn't always be consistent and reliable.
What would be the most efficient manner of accomplishing a smooth updating process? Should I let it update the entire world in one go or do something more incremental?
Edit: It has come to my attention that the pointer acquisition scheme is flawed, but let us assume that the pointers are valid.