Added a fix for a multi-threading bug that occured when TerrainTiles were accessed via the Terrain::_updateTerrainTileSet that were being deleted at the same time by the DatabasePager thread.

This commit is contained in:
Robert Osfield 2012-08-31 16:00:55 +00:00
parent 8961d45ebf
commit f13dd3d75d

View File

@ -97,7 +97,17 @@ void Terrain::traverse(osg::NodeVisitor& nv)
TerrainTileList tiles;
{
OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_mutex);
std::copy(_updateTerrainTileSet.begin(), _updateTerrainTileSet.end(), std::back_inserter(tiles));
for(TerrainTileSet::iterator itr = _updateTerrainTileSet.begin(); itr !=_updateTerrainTileSet.end(); ++itr)
{
// take a reference first to make sure that the referenceCount can be safely read without another thread decrementing it to zero.
(*itr)->ref();
// only if referenceCount is 2 or more indicating there is still a reference held elsewhere is it safe to add it to list of tiles to be updated
if ((*itr)->referenceCount()>1) tiles.push_back(*itr);
// use unref_nodelete to avoid any issues when the *itr TerrainTile has been deleted by another thread while this for loop has been running.
(*itr)->unref_nodelete();
}
_updateTerrainTileSet.clear();
}