]> git.tdb.fi Git - libs/gl.git/blobdiff - source/resourcemanager.cpp
Implement automatic unloading when a total size limit is exceeded
[libs/gl.git] / source / resourcemanager.cpp
index 059c29241335d464835bb3557bb8c6c98cc93a12..8b647f31f9ef24f5bd7d13d2ae5bb46f46b54c98 100644 (file)
@@ -9,7 +9,9 @@ namespace GL {
 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)
@@ -33,6 +35,16 @@ void ResourceManager::set_async_loads(bool a)
        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;
@@ -101,8 +113,12 @@ void ResourceManager::remove_resource(Resource &r)
 void ResourceManager::tick()
 {
        LoadingThread::State thread_state = thread.get_state();
+       bool check_total_size = false;
        if(thread_state==LoadingThread::SYNC_PENDING)
+       {
                thread.sync();
+               check_total_size = true;
+       }
        else if(thread_state==LoadingThread::IDLE && !queue.empty())
        {
                ManagedResource *managed = queue.front();
@@ -128,6 +144,40 @@ void ResourceManager::tick()
                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;
 }
 
 
@@ -137,7 +187,8 @@ ResourceManager::ManagedResource::ManagedResource(Resource &r):
        io(0),
        loader(0),
        loaded(false),
-       last_used(0)
+       last_used(0),
+       data_size(0)
 { }
 
 void ResourceManager::ManagedResource::start_loading()
@@ -159,6 +210,7 @@ void ResourceManager::ManagedResource::finish_loading()
        loaded = true;
        delete io;
        io = 0;
+       data_size = resource->get_data_size();
 }
 
 void ResourceManager::ManagedResource::unload()