forked from teamnwah/openmw-tes3coop
Use a common base class for resource managers
Implement updateCache to delete unreferenced cached objects when they have not been referenced for a while.
This commit is contained in:
parent
ea1efaac0c
commit
df57d4bfba
19 changed files with 152 additions and 105 deletions
|
@ -640,12 +640,15 @@ namespace MWPhysics
|
|||
|
||||
PhysicsSystem::PhysicsSystem(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> parentNode)
|
||||
: mShapeManager(new Resource::BulletShapeManager(resourceSystem->getVFS(), resourceSystem->getSceneManager(), resourceSystem->getNifFileManager()))
|
||||
, mResourceSystem(resourceSystem)
|
||||
, mDebugDrawEnabled(false)
|
||||
, mTimeAccum(0.0f)
|
||||
, mWaterHeight(0)
|
||||
, mWaterEnabled(false)
|
||||
, mParentNode(parentNode)
|
||||
{
|
||||
mResourceSystem->addResourceManager(mShapeManager.get());
|
||||
|
||||
mCollisionConfiguration = new btDefaultCollisionConfiguration();
|
||||
mDispatcher = new btCollisionDispatcher(mCollisionConfiguration);
|
||||
mBroadphase = new btDbvtBroadphase();
|
||||
|
@ -659,6 +662,8 @@ namespace MWPhysics
|
|||
|
||||
PhysicsSystem::~PhysicsSystem()
|
||||
{
|
||||
mResourceSystem->removeResourceManager(mShapeManager.get());
|
||||
|
||||
if (mWaterCollisionObject.get())
|
||||
mCollisionWorld->removeCollisionObject(mWaterCollisionObject.get());
|
||||
|
||||
|
|
|
@ -169,6 +169,7 @@ namespace MWPhysics
|
|||
btCollisionWorld* mCollisionWorld;
|
||||
|
||||
std::auto_ptr<Resource::BulletShapeManager> mShapeManager;
|
||||
Resource::ResourceSystem* mResourceSystem;
|
||||
|
||||
typedef std::map<MWWorld::ConstPtr, Object*> ObjectMap;
|
||||
ObjectMap mObjects;
|
||||
|
|
|
@ -233,7 +233,7 @@ namespace MWRender
|
|||
|
||||
void RenderingManager::clearCache()
|
||||
{
|
||||
mResourceSystem->clearCache();
|
||||
mResourceSystem->updateCache(mViewer->getFrameStamp()->getReferenceTime());
|
||||
if (mTerrain.get())
|
||||
mTerrain->clearCache();
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ add_component_dir (vfs
|
|||
)
|
||||
|
||||
add_component_dir (resource
|
||||
scenemanager keyframemanager imagemanager resourcesystem bulletshapemanager bulletshape niffilemanager objectcache
|
||||
scenemanager keyframemanager imagemanager bulletshapemanager bulletshape niffilemanager objectcache resourcesystem resourcemanager
|
||||
)
|
||||
|
||||
add_component_dir (sceneutil
|
||||
|
|
|
@ -97,10 +97,9 @@ private:
|
|||
};
|
||||
|
||||
BulletShapeManager::BulletShapeManager(const VFS::Manager* vfs, SceneManager* sceneMgr, NifFileManager* nifFileManager)
|
||||
: mVFS(vfs)
|
||||
: ResourceManager(vfs)
|
||||
, mSceneManager(sceneMgr)
|
||||
, mNifFileManager(nifFileManager)
|
||||
, mCache(new osgDB::ObjectCache)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -7,16 +7,7 @@
|
|||
#include <osg/ref_ptr>
|
||||
|
||||
#include "bulletshape.hpp"
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
class Manager;
|
||||
}
|
||||
|
||||
namespace osgDB
|
||||
{
|
||||
class ObjectCache;
|
||||
}
|
||||
#include "resourcemanager.hpp"
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
|
@ -29,7 +20,7 @@ namespace Resource
|
|||
/// Handles loading, caching and "instancing" of bullet shapes.
|
||||
/// A shape 'instance' is a clone of another shape, with the goal of setting a different scale on this instance.
|
||||
/// @note May be used from any thread.
|
||||
class BulletShapeManager
|
||||
class BulletShapeManager : public ResourceManager
|
||||
{
|
||||
public:
|
||||
BulletShapeManager(const VFS::Manager* vfs, SceneManager* sceneMgr, NifFileManager* nifFileManager);
|
||||
|
@ -38,11 +29,8 @@ namespace Resource
|
|||
osg::ref_ptr<BulletShapeInstance> createInstance(const std::string& name);
|
||||
|
||||
private:
|
||||
const VFS::Manager* mVFS;
|
||||
SceneManager* mSceneManager;
|
||||
NifFileManager* mNifFileManager;
|
||||
|
||||
osg::ref_ptr<osgDB::ObjectCache> mCache;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -42,8 +42,7 @@ namespace Resource
|
|||
{
|
||||
|
||||
ImageManager::ImageManager(const VFS::Manager *vfs)
|
||||
: mVFS(vfs)
|
||||
, mCache(new osgDB::ObjectCache)
|
||||
: ResourceManager(vfs)
|
||||
, mWarningImage(createWarningImage())
|
||||
, mOptions(new osgDB::Options("dds_flip dds_dxt1_detect_rgba"))
|
||||
{
|
||||
|
|
|
@ -8,20 +8,16 @@
|
|||
#include <osg/Image>
|
||||
#include <osg/Texture2D>
|
||||
|
||||
#include "resourcemanager.hpp"
|
||||
|
||||
namespace osgViewer
|
||||
{
|
||||
class Viewer;
|
||||
}
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
class Manager;
|
||||
}
|
||||
|
||||
namespace osgDB
|
||||
{
|
||||
class Options;
|
||||
class ObjectCache;
|
||||
}
|
||||
|
||||
namespace Resource
|
||||
|
@ -29,7 +25,7 @@ namespace Resource
|
|||
|
||||
/// @brief Handles loading/caching of Images.
|
||||
/// @note May be used from any thread.
|
||||
class ImageManager
|
||||
class ImageManager : public ResourceManager
|
||||
{
|
||||
public:
|
||||
ImageManager(const VFS::Manager* vfs);
|
||||
|
@ -39,15 +35,9 @@ namespace Resource
|
|||
/// Returns the dummy image if the given image is not found.
|
||||
osg::ref_ptr<osg::Image> getImage(const std::string& filename);
|
||||
|
||||
const VFS::Manager* getVFS() { return mVFS; }
|
||||
|
||||
osg::Image* getWarningImage();
|
||||
|
||||
private:
|
||||
const VFS::Manager* mVFS;
|
||||
|
||||
osg::ref_ptr<osgDB::ObjectCache> mCache;
|
||||
|
||||
osg::ref_ptr<osg::Image> mWarningImage;
|
||||
osg::ref_ptr<osgDB::Options> mOptions;
|
||||
|
||||
|
|
|
@ -9,8 +9,7 @@ namespace Resource
|
|||
{
|
||||
|
||||
KeyframeManager::KeyframeManager(const VFS::Manager* vfs)
|
||||
: mCache(new osgDB::ObjectCache)
|
||||
, mVFS(vfs)
|
||||
: ResourceManager(vfs)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -4,15 +4,7 @@
|
|||
#include <osg/ref_ptr>
|
||||
#include <string>
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
class Manager;
|
||||
}
|
||||
|
||||
namespace osgDB
|
||||
{
|
||||
class ObjectCache;
|
||||
}
|
||||
#include "resourcemanager.hpp"
|
||||
|
||||
namespace NifOsg
|
||||
{
|
||||
|
@ -24,22 +16,15 @@ namespace Resource
|
|||
|
||||
/// @brief Managing of keyframe resources
|
||||
/// @note May be used from any thread.
|
||||
class KeyframeManager
|
||||
class KeyframeManager : public ResourceManager
|
||||
{
|
||||
public:
|
||||
KeyframeManager(const VFS::Manager* vfs);
|
||||
~KeyframeManager();
|
||||
|
||||
void clearCache();
|
||||
|
||||
/// Retrieve a read-only keyframe resource by name (case-insensitive).
|
||||
/// @note Throws an exception if the resource is not found.
|
||||
osg::ref_ptr<const NifOsg::KeyframeHolder> get(const std::string& name);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osgDB::ObjectCache> mCache;
|
||||
|
||||
const VFS::Manager* mVFS;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -29,9 +29,9 @@ namespace Resource
|
|||
};
|
||||
|
||||
NifFileManager::NifFileManager(const VFS::Manager *vfs)
|
||||
: mVFS(vfs)
|
||||
: ResourceManager(vfs, 0.0) // NIF files aren't needed any more when the converted objects are cached in SceneManager / BulletShapeManager,
|
||||
// so we'll use expiryDelay of 0 to instantly delete NIF files after use.
|
||||
{
|
||||
mCache = new osgDB::ObjectCache;
|
||||
}
|
||||
|
||||
NifFileManager::~NifFileManager()
|
||||
|
@ -39,12 +39,6 @@ namespace Resource
|
|||
|
||||
}
|
||||
|
||||
void NifFileManager::clearCache()
|
||||
{
|
||||
// NIF files aren't needed any more when the converted objects are cached in SceneManager / BulletShapeManager,
|
||||
// so we'll simply drop all nif files here, unlikely to need them again
|
||||
mCache->clear();
|
||||
}
|
||||
|
||||
Nif::NIFFilePtr NifFileManager::get(const std::string &name)
|
||||
{
|
||||
|
|
|
@ -5,39 +5,23 @@
|
|||
|
||||
#include <components/nif/niffile.hpp>
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
class Manager;
|
||||
}
|
||||
|
||||
namespace osgDB
|
||||
{
|
||||
class ObjectCache;
|
||||
}
|
||||
#include "resourcemanager.hpp"
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
|
||||
/// @brief Handles caching of NIFFiles.
|
||||
/// @note May be used from any thread.
|
||||
class NifFileManager
|
||||
class NifFileManager : public ResourceManager
|
||||
{
|
||||
public:
|
||||
NifFileManager(const VFS::Manager* vfs);
|
||||
~NifFileManager();
|
||||
|
||||
void clearCache();
|
||||
|
||||
/// Retrieve a NIF file from the cache, or load it from the VFS if not cached yet.
|
||||
/// @note For performance reasons the NifFileManager does not handle case folding, needs
|
||||
/// to be done in advance by other managers accessing the NifFileManager.
|
||||
Nif::NIFFilePtr get(const std::string& name);
|
||||
|
||||
private:
|
||||
// Use the osgDB::ObjectCache so objects are retrieved in thread safe way
|
||||
osg::ref_ptr<osgDB::ObjectCache> mCache;
|
||||
|
||||
const VFS::Manager* mVFS;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
34
components/resource/resourcemanager.cpp
Normal file
34
components/resource/resourcemanager.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include "resourcemanager.hpp"
|
||||
|
||||
#include "objectcache.hpp"
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
|
||||
ResourceManager::ResourceManager(const VFS::Manager *vfs, const double expiryDelay)
|
||||
: mVFS(vfs)
|
||||
, mCache(new osgDB::ObjectCache)
|
||||
, mExpiryDelay(expiryDelay)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ResourceManager::updateCache(double referenceTime)
|
||||
{
|
||||
// NOTE: we could clear the cache from the background thread if the deletion proves too much of an overhead
|
||||
// idea: customize objectCache to not hold a lock while doing the actual deletion
|
||||
mCache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime);
|
||||
mCache->removeExpiredObjectsInCache(referenceTime - mExpiryDelay);
|
||||
}
|
||||
|
||||
void ResourceManager::clearCache()
|
||||
{
|
||||
mCache->clear();
|
||||
}
|
||||
|
||||
const VFS::Manager* ResourceManager::getVFS() const
|
||||
{
|
||||
return mVFS;
|
||||
}
|
||||
|
||||
}
|
43
components/resource/resourcemanager.hpp
Normal file
43
components/resource/resourcemanager.hpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef OPENMW_COMPONENTS_RESOURCE_MANAGER_H
|
||||
#define OPENMW_COMPONENTS_RESOURCE_MANAGER_H
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
class Manager;
|
||||
}
|
||||
|
||||
namespace osgDB
|
||||
{
|
||||
class ObjectCache;
|
||||
}
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
|
||||
/// @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.
|
||||
class ResourceManager
|
||||
{
|
||||
public:
|
||||
/// @param expiryDelay how long to keep objects in cache after no longer being referenced.
|
||||
ResourceManager(const VFS::Manager* vfs, const double expiryDelay = 300.0);
|
||||
|
||||
/// Clear cache entries that have not been referenced for longer than expiryDelay.
|
||||
virtual void updateCache(double referenceTime);
|
||||
|
||||
/// Clear all cache entries regardless of having external references.
|
||||
virtual void clearCache();
|
||||
|
||||
const VFS::Manager* getVFS() const;
|
||||
|
||||
protected:
|
||||
const VFS::Manager* mVFS;
|
||||
osg::ref_ptr<osgDB::ObjectCache> mCache;
|
||||
double mExpiryDelay;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -15,11 +15,21 @@ namespace Resource
|
|||
mKeyframeManager.reset(new KeyframeManager(vfs));
|
||||
mImageManager.reset(new ImageManager(vfs));
|
||||
mSceneManager.reset(new SceneManager(vfs, mImageManager.get(), mNifFileManager.get()));
|
||||
|
||||
addResourceManager(mNifFileManager.get());
|
||||
addResourceManager(mKeyframeManager.get());
|
||||
// note, scene references images so add images afterwards for correct implementation of updateCache()
|
||||
addResourceManager(mSceneManager.get());
|
||||
addResourceManager(mImageManager.get());
|
||||
}
|
||||
|
||||
ResourceSystem::~ResourceSystem()
|
||||
{
|
||||
// this has to be defined in the .cpp file as we can't delete incomplete types
|
||||
|
||||
mResourceManagers.clear();
|
||||
|
||||
// no delete, all handled by auto_ptr
|
||||
}
|
||||
|
||||
SceneManager* ResourceSystem::getSceneManager()
|
||||
|
@ -42,9 +52,24 @@ namespace Resource
|
|||
return mKeyframeManager.get();
|
||||
}
|
||||
|
||||
void ResourceSystem::clearCache()
|
||||
void ResourceSystem::updateCache(double referenceTime)
|
||||
{
|
||||
mNifFileManager->clearCache();
|
||||
osg::Timer timer;
|
||||
for (std::vector<ResourceManager*>::iterator it = mResourceManagers.begin(); it != mResourceManagers.end(); ++it)
|
||||
(*it)->updateCache(referenceTime);
|
||||
std::cout << "updateCache took " << timer.time_m() << " ms" << std::endl;
|
||||
}
|
||||
|
||||
void ResourceSystem::addResourceManager(ResourceManager *resourceMgr)
|
||||
{
|
||||
mResourceManagers.push_back(resourceMgr);
|
||||
}
|
||||
|
||||
void ResourceSystem::removeResourceManager(ResourceManager *resourceMgr)
|
||||
{
|
||||
std::vector<ResourceManager*>::iterator found = std::find(mResourceManagers.begin(), mResourceManagers.end(), resourceMgr);
|
||||
if (found != mResourceManagers.end())
|
||||
mResourceManagers.erase(found);
|
||||
}
|
||||
|
||||
const VFS::Manager* ResourceSystem::getVFS() const
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define OPENMW_COMPONENTS_RESOURCE_RESOURCESYSTEM_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
|
@ -15,6 +16,7 @@ namespace Resource
|
|||
class ImageManager;
|
||||
class NifFileManager;
|
||||
class KeyframeManager;
|
||||
class ResourceManager;
|
||||
|
||||
/// @brief Wrapper class that constructs and provides access to the most commonly used resource subsystems.
|
||||
/// @par Resource subsystems can be used with multiple OpenGL contexts, just like the OSG equivalents, but
|
||||
|
@ -31,8 +33,17 @@ namespace Resource
|
|||
KeyframeManager* getKeyframeManager();
|
||||
|
||||
/// Indicates to each resource manager to clear the cache, i.e. to drop cached objects that are no longer referenced.
|
||||
void clearCache();
|
||||
/// @note May be called from any thread if you do not add or remove resource managers at that point.
|
||||
void updateCache(double referenceTime);
|
||||
|
||||
/// Add this ResourceManager to be handled by the ResourceSystem.
|
||||
/// @note Does not transfer ownership.
|
||||
void addResourceManager(ResourceManager* resourceMgr);
|
||||
/// @note Do nothing if resourceMgr does not exist.
|
||||
/// @note Does not delete resourceMgr.
|
||||
void removeResourceManager(ResourceManager* resourceMgr);
|
||||
|
||||
/// @note May be called from any thread.
|
||||
const VFS::Manager* getVFS() const;
|
||||
|
||||
private:
|
||||
|
@ -41,6 +52,10 @@ namespace Resource
|
|||
std::auto_ptr<NifFileManager> mNifFileManager;
|
||||
std::auto_ptr<KeyframeManager> mKeyframeManager;
|
||||
|
||||
// Store the base classes separately to get convenient access to the common interface
|
||||
// Here users can register their own resourcemanager as well
|
||||
std::vector<ResourceManager*> mResourceManagers;
|
||||
|
||||
const VFS::Manager* mVFS;
|
||||
|
||||
ResourceSystem(const ResourceSystem&);
|
||||
|
|
|
@ -230,7 +230,7 @@ namespace Resource
|
|||
|
||||
|
||||
SceneManager::SceneManager(const VFS::Manager *vfs, Resource::ImageManager* imageManager, Resource::NifFileManager* nifFileManager)
|
||||
: mVFS(vfs)
|
||||
: ResourceManager(vfs)
|
||||
, mImageManager(imageManager)
|
||||
, mNifFileManager(nifFileManager)
|
||||
, mMinFilter(osg::Texture::LINEAR_MIPMAP_LINEAR)
|
||||
|
@ -238,7 +238,6 @@ namespace Resource
|
|||
, mMaxAnisotropy(1)
|
||||
, mUnRefImageDataAfterApply(false)
|
||||
, mParticleSystemMask(~0u)
|
||||
, mCache(new osgDB::ObjectCache)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -403,11 +402,6 @@ namespace Resource
|
|||
node->accept(visitor);
|
||||
}
|
||||
|
||||
const VFS::Manager* SceneManager::getVFS() const
|
||||
{
|
||||
return mVFS;
|
||||
}
|
||||
|
||||
Resource::ImageManager* SceneManager::getImageManager()
|
||||
{
|
||||
return mImageManager;
|
||||
|
@ -483,5 +477,4 @@ namespace Resource
|
|||
mUnRefImageDataAfterApply = unref;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -8,27 +8,19 @@
|
|||
#include <osg/Node>
|
||||
#include <osg/Texture>
|
||||
|
||||
#include "resourcemanager.hpp"
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
class ImageManager;
|
||||
class NifFileManager;
|
||||
}
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
class Manager;
|
||||
}
|
||||
|
||||
namespace osgUtil
|
||||
{
|
||||
class IncrementalCompileOperation;
|
||||
}
|
||||
|
||||
namespace osgDB
|
||||
{
|
||||
class ObjectCache;
|
||||
}
|
||||
|
||||
namespace osgViewer
|
||||
{
|
||||
class Viewer;
|
||||
|
@ -39,7 +31,7 @@ namespace Resource
|
|||
|
||||
/// @brief Handles loading and caching of scenes, e.g. .nif files or .osg files
|
||||
/// @note Some methods of the scene manager can be used from any thread, see the methods documentation for more details.
|
||||
class SceneManager
|
||||
class SceneManager : public ResourceManager
|
||||
{
|
||||
public:
|
||||
SceneManager(const VFS::Manager* vfs, Resource::ImageManager* imageManager, Resource::NifFileManager* nifFileManager);
|
||||
|
@ -78,8 +70,6 @@ namespace Resource
|
|||
/// @note SceneManager::attachTo calls this method automatically, only needs to be called by users if manually attaching
|
||||
void notifyAttached(osg::Node* node) const;
|
||||
|
||||
const VFS::Manager* getVFS() const;
|
||||
|
||||
Resource::ImageManager* getImageManager();
|
||||
|
||||
/// @param mask The node mask to apply to loaded particle system nodes.
|
||||
|
@ -99,7 +89,6 @@ namespace Resource
|
|||
void setUnRefImageDataAfterApply(bool unref);
|
||||
|
||||
private:
|
||||
const VFS::Manager* mVFS;
|
||||
Resource::ImageManager* mImageManager;
|
||||
Resource::NifFileManager* mNifFileManager;
|
||||
|
||||
|
@ -112,8 +101,6 @@ namespace Resource
|
|||
|
||||
unsigned int mParticleSystemMask;
|
||||
|
||||
osg::ref_ptr<osgDB::ObjectCache> mCache;
|
||||
|
||||
SceneManager(const SceneManager&);
|
||||
void operator = (const SceneManager&);
|
||||
};
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace VFS
|
|||
/// @par Various archive types (e.g. directories on the filesystem, or compressed archives)
|
||||
/// can be registered, and will be merged into a single file tree. If the same filename is
|
||||
/// contained in multiple archives, the last added archive will have priority.
|
||||
/// @par Most of the methods in this class are considered thread-safe, see each method documentation for details.
|
||||
class Manager
|
||||
{
|
||||
public:
|
||||
|
@ -33,20 +34,25 @@ namespace VFS
|
|||
void buildIndex();
|
||||
|
||||
/// Does a file with this name exist?
|
||||
/// @note May be called from any thread once the index has been built.
|
||||
bool exists(const std::string& name) const;
|
||||
|
||||
/// Get a complete list of files from all archives
|
||||
/// @note May be called from any thread once the index has been built.
|
||||
const std::map<std::string, File*>& getIndex() const;
|
||||
|
||||
/// Normalize the given filename, making slashes/backslashes consistent, and lower-casing if mStrict is false.
|
||||
/// @note May be called from any thread once the index has been built.
|
||||
void normalizeFilename(std::string& name) const;
|
||||
|
||||
/// Retrieve a file by name.
|
||||
/// @note Throws an exception if the file can not be found.
|
||||
/// @note May be called from any thread once the index has been built.
|
||||
Files::IStreamPtr get(const std::string& name) const;
|
||||
|
||||
/// Retrieve a file by name (name is already normalized).
|
||||
/// @note Throws an exception if the file can not be found.
|
||||
/// @note May be called from any thread once the index has been built.
|
||||
Files::IStreamPtr getNormalized(const std::string& normalizedName) const;
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in a new issue