]> git.tdb.fi Git - libs/gl.git/blobdiff - source/resourcemanager.cpp
Implement automatic resource unloading based on age
[libs/gl.git] / source / resourcemanager.cpp
index 81aea8c16f9af3f006a3030f14708ed5da6894de..059c29241335d464835bb3557bb8c6c98cc93a12 100644 (file)
@@ -9,12 +9,33 @@ namespace GL {
 ResourceManager::ResourceManager():
        policy(LOAD_ON_DEMAND),
        async_loads(true),
+       frame(0),
+       max_retain_frames(0),
+       next_unload(0),
        thread(*this)
 { }
 
 ResourceManager::~ResourceManager()
 {
        thread.terminate();
+
+       for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
+               i->second.resource->set_manager(0);
+}
+
+void ResourceManager::set_loading_policy(LoadingPolicy p)
+{
+       policy = p;
+}
+
+void ResourceManager::set_async_loads(bool a)
+{
+       async_loads = a;
+}
+
+void ResourceManager::set_max_retain_frames(unsigned f)
+{
+       max_retain_frames = f;
 }
 
 void ResourceManager::add_resource(Resource &r)
@@ -22,6 +43,11 @@ void ResourceManager::add_resource(Resource &r)
        insert_unique(resources, &r, ManagedResource(r));
 }
 
+void *ResourceManager::get_data_for_resource(const Resource &r)
+{
+       return &get_item(resources, &r);
+}
+
 void ResourceManager::set_resource_location(Resource &r, DataFile::Collection &c, const string &n)
 {
        ManagedResource &managed = get_item(resources, &r);
@@ -32,7 +58,7 @@ void ResourceManager::set_resource_location(Resource &r, DataFile::Collection &c
                load_resource(r);
 }
 
-void ResourceManager::load_resource(const Resource &r)
+void ResourceManager::load_resource(Resource &r)
 {
        ManagedResource &managed = get_item(resources, &r);
        if(!managed.collection)
@@ -41,10 +67,26 @@ void ResourceManager::load_resource(const Resource &r)
        if(managed.loader)
                return;
 
-       managed.io = managed.collection->open_raw(managed.name);
-       managed.loader = managed.resource->load(*managed.io);
+       managed.start_loading();
 
-       queue.push_back(&managed);
+       if(async_loads)
+               queue.push_back(&managed);
+       else
+       {
+               while(!managed.loader->process()) ;
+               managed.finish_loading();
+       }
+}
+
+void ResourceManager::resource_used(const Resource &r)
+{
+       ManagedResource *managed = reinterpret_cast<ManagedResource *>(r.get_manager_data());
+       if(!managed->loaded && !managed->loader && policy!=LOAD_MANUALLY)
+               load_resource(*managed->resource);
+
+       managed->last_used = frame;
+       if(max_retain_frames && !next_unload)
+               next_unload = frame+max_retain_frames;
 }
 
 void ResourceManager::remove_resource(Resource &r)
@@ -67,6 +109,25 @@ void ResourceManager::tick()
                queue.pop_front();
                thread.set_resource(managed);
        }
+
+       ++frame;
+       if(frame==next_unload)
+       {
+               unsigned unload_limit = frame-max_retain_frames;
+               next_unload = 0;
+
+               for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
+                       if(i->second.loaded)
+                       {
+                               if(i->second.last_used<=unload_limit)
+                                       i->second.unload();
+                               else if(!next_unload || i->second.last_used<next_unload)
+                                       next_unload = i->second.last_used;
+                       }
+
+               if(next_unload)
+                       next_unload += max_retain_frames;
+       }
 }
 
 
@@ -74,9 +135,38 @@ ResourceManager::ManagedResource::ManagedResource(Resource &r):
        resource(&r),
        collection(0),
        io(0),
-       loader(0)
+       loader(0),
+       loaded(false),
+       last_used(0)
 { }
 
+void ResourceManager::ManagedResource::start_loading()
+{
+       io = collection->open_raw(name);
+       loader = resource->load(*io);
+       if(!loader)
+       {
+               delete io;
+               io = 0;
+               throw logic_error("no loader created");
+       }
+}
+
+void ResourceManager::ManagedResource::finish_loading()
+{
+       delete loader;
+       loader = 0;
+       loaded = true;
+       delete io;
+       io = 0;
+}
+
+void ResourceManager::ManagedResource::unload()
+{
+       resource->unload();
+       loaded = false;
+}
+
 
 ResourceManager::LoadingThread::LoadingThread(ResourceManager &m):
        manager(m),
@@ -143,10 +233,7 @@ void ResourceManager::LoadingThread::sync()
 
        if(finished)
        {
-               delete resource->loader;
-               resource->loader = 0;
-               delete resource->io;
-               resource->io = 0;
+               resource->finish_loading();
                resource = 0;
                state = IDLE;
        }