Refactored the handling of use of the osgDB::ObjectCache in the DatabasePager to use a local thread specific ObjectCache to handle new additions and

then have these additions merged with the main Registry ObjectCache during the main loop.


git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14474 16af8721-9629-0410-8352-f15c8da7e697
This commit is contained in:
Robert Osfield
2014-11-13 09:40:11 +00:00
parent ed28ec97c7
commit 25cfb81a09
7 changed files with 127 additions and 64 deletions

View File

@@ -421,6 +421,7 @@ void DatabasePager::DatabaseRequest::invalidate()
_valid = false;
_loadedModel = 0;
_compileSet = 0;
_objectCache = 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -772,15 +773,35 @@ void DatabasePager::DatabaseThread::run()
frameNumberLastRequest = databaseRequest->_frameNumberLastRequest;
}
if (dr_loadOptions->getFileCache()) fileCache = dr_loadOptions->getFileCache();
if (dr_loadOptions->getFileLocationCallback()) fileLocationCallback = dr_loadOptions->getFileLocationCallback();
// disable the FileCache if the fileLocationCallback tells us that it isn't required for this request.
if (fileLocationCallback.valid() && !fileLocationCallback->useFileCache()) fileCache = 0;
cacheNodes = (dr_loadOptions->getObjectCacheHint() & osgDB::Options::CACHE_NODES)!=0;
if (cacheNodes)
{
//OSG_NOTICE<<"Checking main ObjectCache"<<std::endl;
// check the object cache to see if the file we want has already been loaded.
osg::ref_ptr<osg::Object> objectFromCache = osgDB::Registry::instance()->getRefFromObjectCache(fileName);
// if no object with fileName in ObjectCache then try the filename appropriate for fileCache
if (!objectFromCache && (fileCache.valid() && fileCache->isFileAppropriateForFileCache(fileName)))
{
if (fileCache->existsInCache(fileName))
{
objectFromCache = osgDB::Registry::instance()->getRefFromObjectCache(fileCache->createCacheFileName(fileName));
}
}
osg::Node* modelFromCache = dynamic_cast<osg::Node*>(objectFromCache.get());
if (modelFromCache)
{
// OSG_NOTICE<<"Found object in cache "<<fileName<<std::endl;
//OSG_NOTICE<<"Found object in cache "<<fileName<<std::endl;
// assign the cached model to the request
{
@@ -798,18 +819,19 @@ void DatabasePager::DatabaseThread::run()
// skip the rest of the do/while loop as we have done all the processing we need to do.
continue;
}
else
{
//OSG_NOTICE<<"Not Found object in cache "<<fileName<<std::endl;
}
// need to disable any attempt to use the cache when loading as we're handle this ourselves to avoid threading conflicts
dr_loadOptions->setObjectCacheHint(static_cast<osgDB::Options::CacheHintOptions>(dr_loadOptions->getObjectCacheHint() & ~osgDB::Options::CACHE_NODES));
{
OpenThreads::ScopedLock<OpenThreads::Mutex> drLock(_pager->_dr_mutex);
databaseRequest->_objectCache = new ObjectCache;
dr_loadOptions->setObjectCache(databaseRequest->_objectCache.get());
}
}
if (dr_loadOptions->getFileCache()) fileCache = dr_loadOptions->getFileCache();
if (dr_loadOptions->getFileLocationCallback()) fileLocationCallback = dr_loadOptions->getFileLocationCallback();
// disable the FileCache if the fileLocationCallback tells us that it isn't required for this request.
if (fileLocationCallback.valid() && !fileLocationCallback->useFileCache()) fileCache = 0;
// check if databaseRequest is still relevant
if ((_pager->_frameNumber-frameNumberLastRequest)<=1)
@@ -915,31 +937,40 @@ void DatabasePager::DatabaseThread::run()
{
loadedModel->getBound();
// find all the compileable rendering objects
DatabasePager::FindCompileableGLObjectsVisitor stateToCompile(_pager, _pager->getMarkerObject());
loadedModel->accept(stateToCompile);
bool loadedObjectsNeedToBeCompiled = _pager->_doPreCompile &&
_pager->_incrementalCompileOperation.valid() &&
_pager->_incrementalCompileOperation->requiresCompile(stateToCompile);
// move the databaseRequest from the front of the fileRequest to the end of
// dataToCompile or dataToMerge lists.
bool loadedObjectsNeedToBeCompiled = false;
osg::ref_ptr<osgUtil::IncrementalCompileOperation::CompileSet> compileSet = 0;
if (loadedObjectsNeedToBeCompiled)
if (!rr.loadedFromCache())
{
// OSG_NOTICE<<"Using IncrementalCompileOperation"<<std::endl;
// find all the compileable rendering objects
DatabasePager::FindCompileableGLObjectsVisitor stateToCompile(_pager, _pager->getMarkerObject());
loadedModel->accept(stateToCompile);
compileSet = new osgUtil::IncrementalCompileOperation::CompileSet(loadedModel.get());
compileSet->buildCompileMap(_pager->_incrementalCompileOperation->getContextSet(), stateToCompile);
compileSet->_compileCompletedCallback = new DatabasePagerCompileCompletedCallback(_pager, databaseRequest.get());
_pager->_incrementalCompileOperation->add(compileSet.get(), false);
loadedObjectsNeedToBeCompiled = _pager->_doPreCompile &&
_pager->_incrementalCompileOperation.valid() &&
_pager->_incrementalCompileOperation->requiresCompile(stateToCompile);
// move the databaseRequest from the front of the fileRequest to the end of
// dataToCompile or dataToMerge lists.
if (loadedObjectsNeedToBeCompiled)
{
// OSG_NOTICE<<"Using IncrementalCompileOperation"<<std::endl;
compileSet = new osgUtil::IncrementalCompileOperation::CompileSet(loadedModel.get());
compileSet->buildCompileMap(_pager->_incrementalCompileOperation->getContextSet(), stateToCompile);
compileSet->_compileCompletedCallback = new DatabasePagerCompileCompletedCallback(_pager, databaseRequest.get());
_pager->_incrementalCompileOperation->add(compileSet.get(), false);
}
}
else
{
OSG_NOTICE<<"Loaded from ObjectCache"<<std::endl;
}
{
OpenThreads::ScopedLock<OpenThreads::Mutex> drLock(_pager->_dr_mutex);
databaseRequest->_loadedModel = loadedModel;
databaseRequest->_compileSet = compileSet;
databaseRequest->_insertLoadedSubgraphIntoObjectCache = cacheNodes;
}
// Dereference the databaseRequest while the queue is
// locked. This prevents the request from being
@@ -1451,7 +1482,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName, osg::NodePath&
databaseRequest->_group = group;
databaseRequest->_terrain = terrain;
databaseRequest->_loadOptions = loadOptions;
databaseRequest->_insertLoadedSubgraphIntoObjectCache = false;
databaseRequest->_objectCache = 0;
requeue = true;
}
@@ -1484,7 +1515,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName, osg::NodePath&
databaseRequest->_group = group;
databaseRequest->_terrain = terrain;
databaseRequest->_loadOptions = loadOptions;
databaseRequest->_insertLoadedSubgraphIntoObjectCache = false;
databaseRequest->_objectCache = 0;
_fileRequestQueue->addNoLock(databaseRequest.get());
}
@@ -1663,11 +1694,10 @@ void DatabasePager::addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp)
registerPagedLODs(databaseRequest->_loadedModel.get(), frameNumber);
}
if (databaseRequest->_insertLoadedSubgraphIntoObjectCache)
if (databaseRequest->_objectCache.valid() && osgDB::Registry::instance()->getObjectCache())
{
// insert loaded model into Registry ObjectCache
// OSG_NOTICE<<"Inserting loaded Model ("<<databaseRequest->_fileName<<") into ObjectCache"<<std::endl;
osgDB::Registry::instance()->addEntryToObjectCache( databaseRequest->_fileName, databaseRequest->_loadedModel.get(), timeStamp);
osgDB::Registry::instance()->getObjectCache()->addObjectCache( databaseRequest->_objectCache.get());
}
// OSG_NOTICE<<"merged subgraph"<<databaseRequest->_fileName<<" after "<<databaseRequest->_numOfRequests<<" requests and time="<<(timeStamp-databaseRequest->_timestampFirstRequest)*1000.0<<std::endl;

View File

@@ -22,14 +22,27 @@ using namespace osgDB;
ObjectCache::ObjectCache():
osg::Referenced(true)
{
OSG_NOTICE<<"Constructed ObjectCach"<<std::endl;
// OSG_NOTICE<<"Constructed ObjectCach"<<std::endl;
}
ObjectCache::~ObjectCache()
{
OSG_NOTICE<<"Destructed ObjectCach"<<std::endl;
// OSG_NOTICE<<"Destructed ObjectCach"<<std::endl;
}
void ObjectCache::addObjectCache(ObjectCache* objectCache)
{
// don't allow a cache to be added to itself.
if (objectCache==this) return;
// lock both ObjectCache to prevent their contents from being modified by other threads while we merge.
OpenThreads::ScopedLock<OpenThreads::Mutex> lock1(_objectCacheMutex);
OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(objectCache->_objectCacheMutex);
// OSG_NOTICE<<"Inserting objects to main ObjectCache "<<objectCache->_objectCache.size()<<std::endl;
_objectCache.insert(objectCache->_objectCache.begin(), objectCache->_objectCache.end());
}
void ObjectCache::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp)
@@ -50,7 +63,11 @@ osg::ref_ptr<osg::Object> ObjectCache::getRefFromObjectCache(const std::string&
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
ObjectCacheMap::iterator itr = _objectCache.find(fileName);
if (itr!=_objectCache.end()) return itr->second.first;
if (itr!=_objectCache.end())
{
// OSG_NOTICE<<"Found "<<fileName<<" in ObjectCache "<<this<<std::endl;
return itr->second.first;
}
else return 0;
}

View File

@@ -21,6 +21,7 @@ Options::Options(const Options& options,const osg::CopyOp& copyop):
_str(options._str),
_databasePaths(options._databasePaths),
_objectCacheHint(options._objectCacheHint),
_objectCache(options._objectCache),
_precisionHint(options._precisionHint),
_buildKdTreesHint(options._buildKdTreesHint),
_pluginData(options._pluginData),

View File

@@ -1245,43 +1245,46 @@ ReaderWriter::ReadResult Registry::readImplementation(const ReadFunctor& readFun
{
std::string file(readFunctor._filename);
bool useObjectCache=false;
bool useObjectCache = false;
const Options* options = readFunctor._options;
ObjectCache* optionsCache = options ? options->getObjectCache() : 0;
//Note CACHE_ARCHIVES has a different object that it caches to so it will never be used here
if (_objectCache.valid() && cacheHint!=Options::CACHE_ARCHIVES)
if ((optionsCache || _objectCache.valid()) && cacheHint!=Options::CACHE_ARCHIVES)
{
const Options* options=readFunctor._options;
useObjectCache=options ? (options->getObjectCacheHint()&cacheHint)!=0: false;
useObjectCache= options ? (options->getObjectCacheHint()&cacheHint)!=0: false;
}
if (useObjectCache)
{
// search for entry in the object cache.
osg::ref_ptr<osg::Object> object = optionsCache ? optionsCache->getRefFromObjectCache(file) : 0;
if (!object && _objectCache.valid()) object = _objectCache->getRefFromObjectCache(file);
if (object.valid())
{
osg::ref_ptr<osg::Object> object = _objectCache->getRefFromObjectCache(file);
if (object.valid())
{
OSG_INFO<<"returning cached instanced of "<<file<<std::endl;
if (readFunctor.isValid(object.get())) return ReaderWriter::ReadResult(object.get(), ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
else return ReaderWriter::ReadResult("Error file does not contain an osg::Object");
}
if (readFunctor.isValid(object.get())) return ReaderWriter::ReadResult(object.get(), ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
else return ReaderWriter::ReadResult("Error file does not contain an osg::Object");
}
ReaderWriter::ReadResult rr = read(readFunctor);
if (rr.validObject())
{
// search AGAIN for entry in the object cache.
osg::ref_ptr<osg::Object> object = _objectCache->getRefFromObjectCache(file);
object = _objectCache->getRefFromObjectCache(file);
if (object.valid())
{
OSG_INFO << "returning cached instanced of " << file << std::endl;
if (readFunctor.isValid(object.get())) return ReaderWriter::ReadResult(object.get(), ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
else return ReaderWriter::ReadResult("Error file does not contain an osg::Object");
else
{
return ReaderWriter::ReadResult("Error file does not contain an osg::Object");
}
}
// update cache with new entry.
OSG_INFO<<"Adding to object cache "<<file<<std::endl;
_objectCache->addEntryToObjectCache(file, rr.getObject(), 0.0);
if (optionsCache) optionsCache->addEntryToObjectCache(file, rr.getObject(), 0.0);
else if (_objectCache.valid()) _objectCache->addEntryToObjectCache(file, rr.getObject(), 0.0);
}
else
{