+#include <algorithm>
#include <msp/time/utils.h>
#include "resourcemanager.h"
+#include "resourcewatcher.h"
using namespace std;
ResourceManager::ResourceManager():
policy(LOAD_ON_DEMAND),
async_loads(true),
+ size_limit(0),
frame(0),
+ min_retain_frames(30),
max_retain_frames(0),
next_unload(0),
thread(*this)
async_loads = a;
}
+void ResourceManager::set_size_limit(UInt64 s)
+{
+ size_limit = s;
+}
+
+void ResourceManager::set_min_retain_frames(unsigned f)
+{
+ min_retain_frames = f;
+}
+
void ResourceManager::set_max_retain_frames(unsigned f)
{
max_retain_frames = f;
remove_existing(resources, &r);
}
+void ResourceManager::watch_resource(const Resource &r, ResourceWatcher &w)
+{
+ get_item(resources, &r).add_watcher(w);
+}
+
+void ResourceManager::unwatch_resource(const Resource &r, ResourceWatcher &w)
+{
+ get_item(resources, &r).remove_watcher(w);
+}
+
void ResourceManager::tick()
{
LoadingThread::State thread_state = thread.get_state();
- if(thread_state==LoadingThread::SYNC_PENDING)
+ bool check_total_size = false;
+ if(thread_state==LoadingThread::SYNC_PENDING || thread_state==LoadingThread::LOAD_FINISHED)
+ {
thread.sync();
+ check_total_size = true;
+ }
else if(thread_state==LoadingThread::IDLE && !queue.empty())
{
ManagedResource *managed = queue.front();
if(next_unload)
next_unload += max_retain_frames;
}
+
+ if(check_total_size)
+ {
+ while(get_total_data_size()>size_limit)
+ {
+ unsigned unload_limit = frame-min_retain_frames;
+ ManagedResource *best = 0;
+ UInt64 best_impact = 0;
+ for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
+ if(i->second.loaded && i->second.last_used<unload_limit)
+ {
+ UInt64 impact = i->second.data_size*(frame-i->second.last_used);
+ if(!best || impact>best_impact)
+ {
+ best = &i->second;
+ best_impact = impact;
+ }
+ }
+
+ if(!best)
+ break;
+
+ best->unload();
+ }
+ }
+}
+
+UInt64 ResourceManager::get_total_data_size() const
+{
+ UInt64 total = 0;
+ for(ResourceMap::const_iterator i=resources.begin(); i!=resources.end(); ++i)
+ if(i->second.loaded)
+ total += i->second.data_size;
+ return total;
}
io(0),
loader(0),
loaded(false),
- last_used(0)
+ last_used(0),
+ data_size(0)
{ }
void ResourceManager::ManagedResource::start_loading()
loaded = true;
delete io;
io = 0;
+ data_size = resource->get_data_size();
+
+ for(vector<ResourceWatcher *>::const_iterator i=watchers.begin(); i!=watchers.end(); ++i)
+ (*i)->resource_loaded(*resource);
}
void ResourceManager::ManagedResource::unload()
{
resource->unload();
loaded = false;
+
+ for(vector<ResourceWatcher *>::const_iterator i=watchers.begin(); i!=watchers.end(); ++i)
+ (*i)->resource_unloaded(*resource);
+}
+
+void ResourceManager::ManagedResource::add_watcher(ResourceWatcher &w)
+{
+ if(find(watchers.begin(), watchers.end(), &w)==watchers.end())
+ watchers.push_back(&w);
+}
+
+void ResourceManager::ManagedResource::remove_watcher(ResourceWatcher &w)
+{
+ vector<ResourceWatcher *>::iterator end = remove(watchers.begin(), watchers.end(), &w);
+ if(end!=watchers.end())
+ watchers.erase(end, watchers.end());
}