From c155680d3c8c22ac8dc22ccc540584e3b720990f Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 7 Feb 2016 00:43:37 +0100 Subject: [PATCH] Customize ObjectCache for more efficient locking in removeExpiredObjectsInCache --- components/resource/objectcache.cpp | 37 ++++++++++++++----------- components/resource/objectcache.hpp | 24 ++++++---------- components/resource/resourcemanager.cpp | 2 +- components/resource/resourcemanager.hpp | 8 ++---- components/resource/resourcesystem.cpp | 1 - 5 files changed, 32 insertions(+), 40 deletions(-) diff --git a/components/resource/objectcache.cpp b/components/resource/objectcache.cpp index 7264d05aa7..0c6066417c 100644 --- a/components/resource/objectcache.cpp +++ b/components/resource/objectcache.cpp @@ -11,13 +11,10 @@ * OpenSceneGraph Public License for more details. */ -#include - -#if OSG_VERSION_LESS_THAN(3,3,3) - #include "objectcache.hpp" -using namespace osgDB; +namespace Resource +{ //////////////////////////////////////////////////////////////////////////////////////////// // @@ -95,21 +92,29 @@ void ObjectCache::updateTimeStampOfObjectsInCacheWithExternalReferences(double r void ObjectCache::removeExpiredObjectsInCache(double expiryTime) { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::vector > objectsToRemove; - // Remove expired entries from object cache - ObjectCacheMap::iterator oitr = _objectCache.begin(); - while(oitr != _objectCache.end()) { - if (oitr->second.second<=expiryTime) + OpenThreads::ScopedLock lock(_objectCacheMutex); + + // Remove expired entries from object cache + ObjectCacheMap::iterator oitr = _objectCache.begin(); + while(oitr != _objectCache.end()) { - _objectCache.erase(oitr++); - } - else - { - ++oitr; + if (oitr->second.second<=expiryTime) + { + objectsToRemove.push_back(oitr->second.first); + _objectCache.erase(oitr++); + } + else + { + ++oitr; + } } } + + // note, actual unref happens outside of the lock + objectsToRemove.clear(); } void ObjectCache::removeFromObjectCache(const std::string& fileName) @@ -138,4 +143,4 @@ void ObjectCache::releaseGLObjects(osg::State* state) } } -#endif +} diff --git a/components/resource/objectcache.hpp b/components/resource/objectcache.hpp index cae48ca6b7..624c38bad5 100644 --- a/components/resource/objectcache.hpp +++ b/components/resource/objectcache.hpp @@ -1,3 +1,6 @@ +// Resource ObjectCache for OpenMW, forked from osgDB ObjectCache by Robert Osfield, see copyright notice below. +// The main change from the upstream version is that removeExpiredObjectsInCache no longer keeps a lock while the unref happens. + /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under @@ -11,17 +14,8 @@ * OpenSceneGraph Public License for more details. */ -// Wrapper for osgDB/ObjectCache. Works around ObjectCache not being available in old OSG 3.2. -// Use "#include objectcache.hpp" in place of "#include - -#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3) -#include -#else +#ifndef OPENMW_COMPONENTS_RESOURCE_OBJECTCACHE +#define OPENMW_COMPONENTS_RESOURCE_OBJECTCACHE #include @@ -30,9 +24,9 @@ #include -namespace osgDB { +namespace Resource { -class /*OSGDB_EXPORT*/ ObjectCache : public osg::Referenced +class ObjectCache : public osg::Referenced { public: @@ -70,7 +64,7 @@ class /*OSGDB_EXPORT*/ ObjectCache : public osg::Referenced /** Get an ref_ptr from the object cache*/ osg::ref_ptr getRefFromObjectCache(const std::string& fileName); - /** call rleaseGLObjects on all objects attached to the object cache.*/ + /** call releaseGLObjects on all objects attached to the object cache.*/ void releaseGLObjects(osg::State* state); protected: @@ -88,5 +82,3 @@ class /*OSGDB_EXPORT*/ ObjectCache : public osg::Referenced } #endif - -#endif diff --git a/components/resource/resourcemanager.cpp b/components/resource/resourcemanager.cpp index 60233baa0d..03e6263b91 100644 --- a/components/resource/resourcemanager.cpp +++ b/components/resource/resourcemanager.cpp @@ -7,7 +7,7 @@ namespace Resource ResourceManager::ResourceManager(const VFS::Manager *vfs, const double expiryDelay) : mVFS(vfs) - , mCache(new osgDB::ObjectCache) + , mCache(new Resource::ObjectCache) , mExpiryDelay(expiryDelay) { diff --git a/components/resource/resourcemanager.hpp b/components/resource/resourcemanager.hpp index e45a2e9cb7..a9b6ab3d51 100644 --- a/components/resource/resourcemanager.hpp +++ b/components/resource/resourcemanager.hpp @@ -8,13 +8,9 @@ namespace VFS class Manager; } -namespace osgDB -{ - class ObjectCache; -} - namespace Resource { + class ObjectCache; /// @brief Base class for managers that require a virtual file system and object cache. /// @par This base class implements clearing of the cache, but populating it and what it's used for is up to the individual sub classes. @@ -34,7 +30,7 @@ namespace Resource protected: const VFS::Manager* mVFS; - osg::ref_ptr mCache; + osg::ref_ptr mCache; double mExpiryDelay; }; diff --git a/components/resource/resourcesystem.cpp b/components/resource/resourcesystem.cpp index 1f25bd461f..a8ab6556d7 100644 --- a/components/resource/resourcesystem.cpp +++ b/components/resource/resourcesystem.cpp @@ -54,7 +54,6 @@ namespace Resource void ResourceSystem::updateCache(double referenceTime) { - // TODO: change ObjectCache to not hold lock while the unref happens for (std::vector::iterator it = mResourceManagers.begin(); it != mResourceManagers.end(); ++it) (*it)->updateCache(referenceTime); }