diff options
Diffstat (limited to 'src/resources/resourcemanager.cpp')
-rw-r--r-- | src/resources/resourcemanager.cpp | 79 |
1 files changed, 66 insertions, 13 deletions
diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 658915d2..fb9da9d7 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -21,13 +21,15 @@ * $Id$ */ -#include "resourcemanager.h" - #include <cassert> #include <sstream> +#include <sys/time.h> + #include <physfs.h> #include <SDL_image.h> +#include "resourcemanager.h" + #include "dye.h" #include "image.h" #include "music.h" @@ -41,12 +43,15 @@ ResourceManager *ResourceManager::instance = NULL; ResourceManager::ResourceManager() + : mOldestOrphan(0) { logger->log("Initializing resource manager..."); } ResourceManager::~ResourceManager() { + mResources.insert(mOrphanedResources.begin(), mOrphanedResources.end()); + // Release any remaining spritedefs first because they depend on image sets ResourceIterator iter = mResources.begin(); while (iter != mResources.end()) @@ -82,10 +87,11 @@ ResourceManager::~ResourceManager() } // Release remaining resources, logging the number of dangling references. - while (!mResources.empty()) + iter = mResources.begin(); + while (iter != mResources.end()) { - cleanUp(mResources.begin()->second); - mResources.erase(mResources.begin()); + cleanUp(iter->second); + ++iter; } } @@ -100,6 +106,38 @@ ResourceManager::cleanUp(Resource *res) delete res; } +void ResourceManager::cleanOrphans() +{ + timeval tv; + gettimeofday(&tv, NULL); + // Delete orphaned resources after 30 seconds. + time_t oldest = tv.tv_sec, threshold = oldest - 30; + + if (mOrphanedResources.empty() || mOldestOrphan >= threshold) return; + + ResourceIterator iter = mOrphanedResources.begin(); + while (iter != mOrphanedResources.end()) + { + Resource *res = iter->second; + time_t t = res->mTimeStamp; + if (t >= threshold) + { + if (t < oldest) oldest = t; + ++iter; + } + else + { + logger->log("ResourceManager::release(%s)", res->mIdPath.c_str()); + delete res; + ResourceIterator toErase = iter; + ++iter; + mOrphanedResources.erase(toErase); + } + } + + mOldestOrphan = oldest; +} + bool ResourceManager::setWriteDir(const std::string &path) { @@ -166,13 +204,22 @@ Resource *ResourceManager::get(std::string const &idPath, generator fun, void *d { // Check if the id exists, and return the value if it does. ResourceIterator resIter = mResources.find(idPath); - if (resIter != mResources.end()) { resIter->second->incRef(); return resIter->second; } + resIter = mOrphanedResources.find(idPath); + if (resIter != mOrphanedResources.end()) + { + Resource *res = resIter->second; + mResources.insert(*resIter); + mOrphanedResources.erase(resIter); + res->incRef(); + return res; + } + Resource *resource = fun(data); if (resource) @@ -180,6 +227,7 @@ Resource *ResourceManager::get(std::string const &idPath, generator fun, void *d resource->incRef(); resource->mIdPath = idPath; mResources[idPath] = resource; + cleanOrphans(); } // Returns NULL if the object could not be created. @@ -298,17 +346,22 @@ SpriteDef *ResourceManager::getSprite return static_cast<SpriteDef*>(get(ss.str(), SpriteDefLoader::load, &l)); } -void -ResourceManager::release(const std::string &idPath) +void ResourceManager::release(Resource *res) { - logger->log("ResourceManager::release(%s)", idPath.c_str()); - - ResourceIterator resIter = mResources.find(idPath); + ResourceIterator resIter = mResources.find(res->mIdPath); // The resource has to exist - assert(resIter != mResources.end() && resIter->second); + assert(resIter != mResources.end() && resIter->second == res); + + timeval tv; + gettimeofday(&tv, NULL); + time_t timestamp = tv.tv_sec; + + res->mTimeStamp = timestamp; + if (mOrphanedResources.empty()) mOldestOrphan = timestamp; - mResources.erase(idPath); + mOrphanedResources.insert(*resIter); + mResources.erase(resIter); } ResourceManager* |