From 85cd1c456f5752628ab43c206f83b263fc04504c Mon Sep 17 00:00:00 2001 From: Ralf Habacker Date: Wed, 15 Jan 2014 15:33:42 +0100 Subject: [PATCH] Identify files in object cache by filename and optional provided options. Objects with the same filename may be different from others based on the provided plugin options. Using filename *and* the provided options as object cache key helps to avoid fetching the wrong object. --- include/osgDB/ObjectCache | 11 ++++++----- include/osgDB/Options | 6 ++++-- include/osgDB/Registry | 8 ++++---- src/osgDB/ObjectCache.cpp | 39 +++++++++++++++++++++++++++------------ src/osgDB/Options.cpp | 14 ++++++++++++++ src/osgDB/Registry.cpp | 26 +++++++++++++------------- 6 files changed, 68 insertions(+), 36 deletions(-) diff --git a/include/osgDB/ObjectCache b/include/osgDB/ObjectCache index 624356d14..d6179b51a 100644 --- a/include/osgDB/ObjectCache +++ b/include/osgDB/ObjectCache @@ -50,16 +50,16 @@ class OSGDB_EXPORT ObjectCache : public osg::Referenced void addObjectCache(ObjectCache* object); /** Add a filename,object,timestamp triple to the Registry::ObjectCache.*/ - void addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp = 0.0); + void addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp = 0.0, const Options *options = NULL); /** Remove Object from cache.*/ - void removeFromObjectCache(const std::string& fileName); + void removeFromObjectCache(const std::string& fileName, const Options *options = NULL); /** Get an Object from the object cache*/ - osg::Object* getFromObjectCache(const std::string& fileName); + osg::Object* getFromObjectCache(const std::string& fileName, const Options *options = NULL); /** Get an ref_ptr from the object cache*/ - osg::ref_ptr getRefFromObjectCache(const std::string& fileName); + osg::ref_ptr getRefFromObjectCache(const std::string& fileName, const Options *options = NULL); /** call rleaseGLObjects on all objects attached to the object cache.*/ void releaseGLObjects(osg::State* state); @@ -69,7 +69,8 @@ class OSGDB_EXPORT ObjectCache : public osg::Referenced virtual ~ObjectCache(); typedef std::pair, double > ObjectTimeStampPair; - typedef std::map ObjectCacheMap; + typedef std::pair > FileNameOptionsPair; + typedef std::map ObjectCacheMap; ObjectCacheMap _objectCache; OpenThreads::Mutex _objectCacheMutex; diff --git a/include/osgDB/Options b/include/osgDB/Options index 972221686..0790161de 100644 --- a/include/osgDB/Options +++ b/include/osgDB/Options @@ -255,10 +255,12 @@ class OSGDB_EXPORT Options : public osg::Object /** Get the parentGroup observer_ptr, where the loaded model is intended to be added */ const osg::observer_ptr& getParentGroup() const { return _parentGroup; } - protected: - + bool operator < (const Options &rhs) const; + bool operator == (const Options &rhs) const; virtual ~Options() {} + protected: + std::string _str; FilePathList _databasePaths; diff --git a/include/osgDB/Registry b/include/osgDB/Registry index 6851ccc55..62d4ac884 100644 --- a/include/osgDB/Registry +++ b/include/osgDB/Registry @@ -452,16 +452,16 @@ class OSGDB_EXPORT Registry : public osg::Referenced void clearObjectCache(); /** Add a filename,object,timestamp triple to the Registry::ObjectCache.*/ - void addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp = 0.0); + void addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp = 0.0, Options *options = NULL); /** Remove Object from cache.*/ - void removeFromObjectCache(const std::string& fileName); + void removeFromObjectCache(const std::string& fileName, Options *options = NULL); /** Get an Object from the object cache*/ - osg::Object* getFromObjectCache(const std::string& fileName); + osg::Object* getFromObjectCache(const std::string& fileName, Options *options = NULL); /** Get an ref_ptr from the object cache*/ - osg::ref_ptr getRefFromObjectCache(const std::string& fileName); + osg::ref_ptr getRefFromObjectCache(const std::string& fileName, Options *options = NULL); diff --git a/src/osgDB/ObjectCache.cpp b/src/osgDB/ObjectCache.cpp index 8779711e2..856b3d434 100644 --- a/src/osgDB/ObjectCache.cpp +++ b/src/osgDB/ObjectCache.cpp @@ -12,6 +12,7 @@ */ #include +#include using namespace osgDB; @@ -39,34 +40,48 @@ void ObjectCache::addObjectCache(ObjectCache* objectCache) OpenThreads::ScopedLock lock1(_objectCacheMutex); OpenThreads::ScopedLock lock2(objectCache->_objectCacheMutex); - // OSG_NOTICE<<"Inserting objects to main ObjectCache "<_objectCache.size()<_objectCache.size()<_objectCache.begin(), objectCache->_objectCache.end()); } -void ObjectCache::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp) +void ObjectCache::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp, const Options *options) { OpenThreads::ScopedLock lock(_objectCacheMutex); - _objectCache[filename]=ObjectTimeStampPair(object,timestamp); + _objectCache[FileNameOptionsPair(filename, osg::clone(options))] = ObjectTimeStampPair(object,timestamp); + OSG_DEBUG<<"Adding "<getOptionString() : "")<<"' to ObjectCache "< lock(_objectCacheMutex); - ObjectCacheMap::iterator itr = _objectCache.find(fileName); - if (itr!=_objectCache.end()) return itr->second.first.get(); + ObjectCacheMap::iterator itr = _objectCache.find(FileNameOptionsPair(fileName, options)); + if (itr!=_objectCache.end()) + { + osg::ref_ptr o = itr->first.second; + if (o.valid()) + OSG_DEBUG<<"Found "<getOptionString()<< "' in ObjectCache "<second.first.get(); + } else return 0; } -osg::ref_ptr ObjectCache::getRefFromObjectCache(const std::string& fileName) +osg::ref_ptr ObjectCache::getRefFromObjectCache(const std::string& fileName, const Options *options) { OpenThreads::ScopedLock lock(_objectCacheMutex); - ObjectCacheMap::iterator itr = _objectCache.find(fileName); + ObjectCacheMap::iterator itr; + itr = _objectCache.find(FileNameOptionsPair(fileName, options)); if (itr!=_objectCache.end()) { - // OSG_NOTICE<<"Found "<second.first; + osg::ref_ptr o = itr->first.second; + if (o.valid()) + OSG_DEBUG<<"Found "<getOptionString()<< "' in ObjectCache "<second.first.get(); } else return 0; } @@ -108,10 +123,10 @@ void ObjectCache::removeExpiredObjectsInCache(double expiryTime) } } -void ObjectCache::removeFromObjectCache(const std::string& fileName) +void ObjectCache::removeFromObjectCache(const std::string& fileName, const Options *options) { OpenThreads::ScopedLock lock(_objectCacheMutex); - ObjectCacheMap::iterator itr = _objectCache.find(fileName); + ObjectCacheMap::iterator itr = _objectCache.find(FileNameOptionsPair(fileName, options)); if (itr!=_objectCache.end()) _objectCache.erase(itr); } diff --git a/src/osgDB/Options.cpp b/src/osgDB/Options.cpp index 1b963b801..1841fcaf2 100644 --- a/src/osgDB/Options.cpp +++ b/src/osgDB/Options.cpp @@ -56,3 +56,17 @@ void Options::parsePluginStringData(const std::string& str, char separator1, cha } } } + +bool Options::operator <(const Options &rhs) const +{ + // TODO add better compare + //OSG_DEBUG << "comparing <'" << _str << "' with '" << rhs._str << "'" << std::endl; + return _str.compare(rhs._str) < 0; +} + +bool Options::operator ==(const Options &rhs) const +{ + // TODO add better compare + //OSG_DEBUG << "comparing == '" << _str << "' with '" << rhs._str << "'" << std::endl; + return _str.compare(rhs._str) == 0; +} diff --git a/src/osgDB/Registry.cpp b/src/osgDB/Registry.cpp index 557f639e5..386fcacc0 100644 --- a/src/osgDB/Registry.cpp +++ b/src/osgDB/Registry.cpp @@ -1250,9 +1250,9 @@ ReaderWriter::ReadResult Registry::readImplementation(const ReadFunctor& readFun if (useObjectCache) { // search for entry in the object cache. - osg::ref_ptr object = optionsCache ? optionsCache->getRefFromObjectCache(file) : 0; + osg::ref_ptr object = optionsCache ? optionsCache->getRefFromObjectCache(file, options) : 0; - if (!object && _objectCache.valid()) object = _objectCache->getRefFromObjectCache(file); + if (!object && _objectCache.valid()) object = _objectCache->getRefFromObjectCache(file, options); if (object.valid()) { @@ -1264,7 +1264,7 @@ ReaderWriter::ReadResult Registry::readImplementation(const ReadFunctor& readFun if (rr.validObject()) { // search AGAIN for entry in the object cache. - object = _objectCache->getRefFromObjectCache(file); + object = _objectCache->getRefFromObjectCache(file, options); if (object.valid()) { if (readFunctor.isValid(object.get())) return ReaderWriter::ReadResult(object.get(), ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE); @@ -1275,8 +1275,8 @@ ReaderWriter::ReadResult Registry::readImplementation(const ReadFunctor& readFun } // update cache with new entry. - if (optionsCache) optionsCache->addEntryToObjectCache(file, rr.getObject(), 0.0); - else if (_objectCache.valid()) _objectCache->addEntryToObjectCache(file, rr.getObject(), 0.0); + if (optionsCache) optionsCache->addEntryToObjectCache(file, rr.getObject(), 0.0, options); + else if (_objectCache.valid()) _objectCache->addEntryToObjectCache(file, rr.getObject(), 0.0, options); } else { @@ -1597,19 +1597,19 @@ ReaderWriter::WriteResult Registry::writeScriptImplementation(const Script& imag return result; } -void Registry::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp) +void Registry::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp, Options *options) { - if (_objectCache.valid()) _objectCache->addEntryToObjectCache(filename, object, timestamp); + if (_objectCache.valid()) _objectCache->addEntryToObjectCache(filename, object, timestamp, options); } -osg::Object* Registry::getFromObjectCache(const std::string& filename) +osg::Object* Registry::getFromObjectCache(const std::string& filename, Options *options) { - return _objectCache.valid() ? _objectCache->getFromObjectCache(filename) : 0; + return _objectCache.valid() ? _objectCache->getFromObjectCache(filename, options) : 0; } -osg::ref_ptr Registry::getRefFromObjectCache(const std::string& filename) +osg::ref_ptr Registry::getRefFromObjectCache(const std::string& filename, Options *options) { - return _objectCache.valid() ? _objectCache->getRefFromObjectCache(filename) : 0; + return _objectCache.valid() ? _objectCache->getRefFromObjectCache(filename, options) : 0; } void Registry::updateTimeStampOfObjectsInCacheWithExternalReferences(const osg::FrameStamp& frameStamp) @@ -1623,9 +1623,9 @@ void Registry::removeExpiredObjectsInCache(const osg::FrameStamp& frameStamp) if (_objectCache.valid()) _objectCache->removeExpiredObjectsInCache(expiryTime); } -void Registry::removeFromObjectCache(const std::string& filename) +void Registry::removeFromObjectCache(const std::string& filename, Options *options) { - if (_objectCache.valid()) _objectCache->removeFromObjectCache(filename); + if (_objectCache.valid()) _objectCache->removeFromObjectCache(filename, options); } void Registry::clearObjectCache()