]> git.tdb.fi Git - libs/gl.git/commitdiff
Implement automatic resource unloading based on age
authorMikko Rasa <tdb@tdb.fi>
Mon, 8 Sep 2014 18:28:22 +0000 (21:28 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 8 Sep 2014 19:35:32 +0000 (22:35 +0300)
source/resourcemanager.cpp
source/resourcemanager.h

index cc69b895aa2ecd33196df0b087e0d3521ee2999c..059c29241335d464835bb3557bb8c6c98cc93a12 100644 (file)
@@ -9,6 +9,9 @@ namespace GL {
 ResourceManager::ResourceManager():
        policy(LOAD_ON_DEMAND),
        async_loads(true),
+       frame(0),
+       max_retain_frames(0),
+       next_unload(0),
        thread(*this)
 { }
 
@@ -30,6 +33,11 @@ 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)
 {
        insert_unique(resources, &r, ManagedResource(r));
@@ -75,6 +83,10 @@ 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)
@@ -97,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;
+       }
 }
 
 
@@ -105,7 +136,8 @@ ResourceManager::ManagedResource::ManagedResource(Resource &r):
        collection(0),
        io(0),
        loader(0),
-       loaded(false)
+       loaded(false),
+       last_used(0)
 { }
 
 void ResourceManager::ManagedResource::start_loading()
@@ -129,6 +161,12 @@ void ResourceManager::ManagedResource::finish_loading()
        io = 0;
 }
 
+void ResourceManager::ManagedResource::unload()
+{
+       resource->unload();
+       loaded = false;
+}
+
 
 ResourceManager::LoadingThread::LoadingThread(ResourceManager &m):
        manager(m),
index 1e3cb54f3b439c72fe26811ccd546d6993743327..07b0aaf09f0574fe2ee8f6fbaea7be162f9660b7 100644 (file)
@@ -29,11 +29,13 @@ private:
                IO::Seekable *io;
                Resource::AsyncLoader *loader;
                bool loaded;
+               unsigned last_used;
 
                ManagedResource(Resource &);
 
                void start_loading();
                void finish_loading();
+               void unload();
        };
 
        class LoadingThread: public Thread
@@ -76,6 +78,10 @@ private:
        bool async_loads;
        ResourceMap resources;
        LoadQueue queue;
+       unsigned frame;
+       unsigned min_retain_frames;
+       unsigned max_retain_frames;
+       unsigned next_unload;
        LoadingThread thread;
 
 public:
@@ -84,6 +90,7 @@ public:
 
        void set_loading_policy(LoadingPolicy);
        void set_async_loads(bool);
+       void set_max_retain_frames(unsigned);
 
        void add_resource(Resource &);
        void *get_data_for_resource(const Resource &);