From 0e9c93f335e5ed95a1b063f40a4c4ff71530f4ba Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 10 Nov 2014 16:04:43 +0000 Subject: [PATCH] To handle thread safe paging and use of the osgDB::Registry ObjectCache, moved the handling of cache into osgDB::DatabasePager. git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14472 16af8721-9629-0410-8352-f15c8da7e697 --- include/osgDB/DatabasePager | 13 +++++---- src/osgDB/DatabasePager.cpp | 56 +++++++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/include/osgDB/DatabasePager b/include/osgDB/DatabasePager index f5e3bb934..1c9efd9b8 100644 --- a/include/osgDB/DatabasePager +++ b/include/osgDB/DatabasePager @@ -311,13 +311,19 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl _timestampLastRequest(0.0), _priorityLastRequest(0.0f), _numOfRequests(0), - _groupExpired(false) + _groupExpired(false), + _insertLoadedSubgraphIntoObjectCache(false) {} void invalidate(); bool valid() const { return _valid; } + bool isRequestCurrent (int frameNumber) const + { + return _valid && (frameNumber - _frameNumberLastRequest <= 1); + } + bool _valid; std::string _fileName; unsigned int _frameNumberFirstRequest; @@ -337,10 +343,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl osg::observer_ptr _compileSet; bool _groupExpired; // flag used only in update thread - bool isRequestCurrent (int frameNumber) const - { - return _valid && (frameNumber - _frameNumberLastRequest <= 1); - } + bool _insertLoadedSubgraphIntoObjectCache; }; diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index f5ede57d1..d62ec262b 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -761,27 +761,51 @@ void DatabasePager::DatabaseThread::run() osg::ref_ptr dr_loadOptions; std::string fileName; int frameNumberLastRequest = 0; + bool cacheNodes = false; if (databaseRequest.valid()) { { OpenThreads::ScopedLock drLock(_pager->_dr_mutex); - dr_loadOptions = databaseRequest->_loadOptions; + dr_loadOptions = databaseRequest->_loadOptions.valid() ? databaseRequest->_loadOptions->cloneOptions() : new osgDB::Options; + dr_loadOptions->setTerrain(databaseRequest->_terrain); fileName = databaseRequest->_fileName; frameNumberLastRequest = databaseRequest->_frameNumberLastRequest; } - if (dr_loadOptions.valid()) - { - if (dr_loadOptions->getFileCache()) fileCache = dr_loadOptions->getFileCache(); - if (dr_loadOptions->getFileLocationCallback()) fileLocationCallback = dr_loadOptions->getFileLocationCallback(); - dr_loadOptions = dr_loadOptions->cloneOptions(); - } - else + cacheNodes = (dr_loadOptions->getObjectCacheHint() & osgDB::Options::CACHE_NODES)!=0; + if (cacheNodes) { - dr_loadOptions = new osgDB::Options; + // check the object cache to see if the file we want has already been loaded. + osg::ref_ptr objectFromCache = osgDB::Registry::instance()->getRefFromObjectCache(fileName); + osg::Node* modelFromCache = dynamic_cast(objectFromCache.get()); + if (modelFromCache) + { + // OSG_NOTICE<<"Found object in cache "< drLock(_pager->_dr_mutex); + databaseRequest->_loadedModel = modelFromCache; + } + + // move the request to the dataToMerge list so it can be merged during the update phase of the frame. + { + OpenThreads::ScopedLock listLock( _pager->_dataToMergeList->_requestMutex); + _pager->_dataToMergeList->addNoLock(databaseRequest.get()); + databaseRequest = 0; + } + + // skip the rest of the do/while loop as we have done all the processing we need to do. + continue; + } + + // 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(dr_loadOptions->getObjectCacheHint() & ~osgDB::Options::CACHE_NODES)); } - dr_loadOptions->setTerrain(databaseRequest->_terrain); + 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; @@ -915,6 +939,7 @@ void DatabasePager::DatabaseThread::run() OpenThreads::ScopedLock 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 @@ -1339,8 +1364,6 @@ void DatabasePager::requestNodeFile(const std::string& fileName, osg::NodePath& if (!loadOptions) { loadOptions = Registry::instance()->getOptions(); - - // OSG_NOTICE<<"Using options from Registry "<_group = group; databaseRequest->_terrain = terrain; databaseRequest->_loadOptions = loadOptions; + databaseRequest->_insertLoadedSubgraphIntoObjectCache = false; requeue = true; } @@ -1460,6 +1484,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName, osg::NodePath& databaseRequest->_group = group; databaseRequest->_terrain = terrain; databaseRequest->_loadOptions = loadOptions; + databaseRequest->_insertLoadedSubgraphIntoObjectCache = false; _fileRequestQueue->addNoLock(databaseRequest.get()); } @@ -1638,6 +1663,13 @@ void DatabasePager::addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp) registerPagedLODs(databaseRequest->_loadedModel.get(), frameNumber); } + if (databaseRequest->_insertLoadedSubgraphIntoObjectCache) + { + // insert loaded model into Registry ObjectCache + // OSG_NOTICE<<"Inserting loaded Model ("<_fileName<<") into ObjectCache"<addEntryToObjectCache( databaseRequest->_fileName, databaseRequest->_loadedModel.get(), timeStamp); + } + // OSG_NOTICE<<"merged subgraph"<_fileName<<" after "<_numOfRequests<<" requests and time="<<(timeStamp-databaseRequest->_timestampFirstRequest)*1000.0<_timestampFirstRequest;