summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/resources/resource.cpp12
-rw-r--r--src/resources/resource.h6
-rw-r--r--src/resources/resourcemanager.cpp79
-rw-r--r--src/resources/resourcemanager.h14
4 files changed, 87 insertions, 24 deletions
diff --git a/src/resources/resource.cpp b/src/resources/resource.cpp
index 07f31b8f..8f21f5d2 100644
--- a/src/resources/resource.cpp
+++ b/src/resources/resource.cpp
@@ -21,10 +21,10 @@
* $Id$
*/
-#include "resource.h"
-
#include <cassert>
+#include "resource.h"
+
#include "resourcemanager.h"
Resource::~Resource()
@@ -45,10 +45,10 @@ Resource::decRef()
mRefCount--;
- if (mRefCount == 0) {
- // Make sure resource manager won't refer to deleted resource
+ if (mRefCount == 0)
+ {
+ // Warn the manager that this resource is no longer used.
ResourceManager *resman = ResourceManager::getInstance();
- resman->release(mIdPath);
- delete this;
+ resman->release(this);
}
}
diff --git a/src/resources/resource.h b/src/resources/resource.h
index 7c39f176..5b9a5eb8 100644
--- a/src/resources/resource.h
+++ b/src/resources/resource.h
@@ -24,6 +24,7 @@
#ifndef _TMW_RESOURCE_H
#define _TMW_RESOURCE_H
+#include <ctime>
#include <string>
/**
@@ -69,8 +70,9 @@ class Resource
~Resource();
private:
- unsigned int mRefCount; /**< Reference count */
- std::string mIdPath; /**< Path identifying this resource */
+ std::string mIdPath; /**< Path identifying this resource. */
+ time_t mTimeStamp; /**< Time at which the resource was orphaned. */
+ unsigned mRefCount; /**< Reference count. */
};
#endif
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*
diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h
index 1adb8446..abfd629a 100644
--- a/src/resources/resourcemanager.h
+++ b/src/resources/resourcemanager.h
@@ -24,6 +24,7 @@
#ifndef _TMW_RESOURCE_MANAGER_H
#define _TMW_RESOURCE_MANAGER_H
+#include <ctime>
#include <map>
#include <string>
#include <vector>
@@ -41,7 +42,11 @@ struct SDL_Surface;
*/
class ResourceManager
{
+
+ friend class Resource;
+
public:
+
typedef Resource *(*loader)(void *, unsigned);
typedef Resource *(*generator)(void *);
@@ -156,10 +161,9 @@ class ResourceManager
SpriteDef *getSprite(std::string const &path, int variant = 0);
/**
- * Releases a resource, removing it from the set of loaded resources.
+ * Releases a resource, placing it in the set of orphaned resources.
*/
- void
- release(const std::string &idPath);
+ void release(Resource *);
/**
* Allocates data into a buffer pointer for raw data loading. The
@@ -207,10 +211,14 @@ class ResourceManager
static void
cleanUp(Resource *resource);
+ void cleanOrphans();
+
static ResourceManager *instance;
typedef std::map<std::string, Resource*> Resources;
typedef Resources::iterator ResourceIterator;
Resources mResources;
+ Resources mOrphanedResources;
+ time_t mOldestOrphan;
};
#endif