]> git.tdb.fi Git - libs/gl.git/blobdiff - source/resourcemanager.cpp
Remember the camera given to Renderer constructor
[libs/gl.git] / source / resourcemanager.cpp
index 733cfaff8c4c37ba5ae1ffbd605ceb3f8d6a58df..4b72685d4d4ba6f4594a2349101cc253b9ecd36f 100644 (file)
@@ -4,7 +4,8 @@
 #include <msp/strings/format.h>
 #include <msp/time/utils.h>
 #include "resourcemanager.h"
-#include "resourcewatcher.h"
+#include "resources.h"
+#include "resourceobserver.h"
 
 using namespace std;
 
@@ -23,6 +24,7 @@ resource_load_error::resource_load_error(const string &name, const exception &ex
 ResourceManager::ResourceManager():
        policy(LOAD_ON_DEMAND),
        async_loads(true),
+       total_data_size(0),
        size_limit(0),
        frame(0),
        min_retain_frames(30),
@@ -65,12 +67,20 @@ void ResourceManager::set_max_retain_frames(unsigned f)
 
 void ResourceManager::add_resource(Resource &r)
 {
+       MutexLock lock(map_mutex);
        insert_unique(resources, &r, ManagedResource(r));
 }
 
-void *ResourceManager::get_data_for_resource(const Resource &r)
+const ResourceManager::ManagedResource &ResourceManager::get_managed_resource(const Resource &r) const
 {
-       return &get_item(resources, &r);
+       MutexLock lock(map_mutex);
+       return get_item(resources, &r);
+}
+
+ResourceManager::ManagedResource &ResourceManager::get_managed_resource(const Resource &r)
+{
+       MutexLock lock(map_mutex);
+       return get_item(resources, &r);
 }
 
 void ResourceManager::set_resource_location(Resource &r, DataFile::Collection &c, const string &n)
@@ -80,8 +90,11 @@ void ResourceManager::set_resource_location(Resource &r, DataFile::Collection &c
 
 void ResourceManager::set_resource_location(Resource &r, const ResourceLocation &l)
 {
-       ManagedResource &managed = get_item(resources, &r);
-       managed.location = l;
+       {
+               MutexLock lock(map_mutex);
+               ManagedResource &managed = get_item(resources, &r);
+               managed.location = l;
+       }
 
        if(policy==LOAD_IMMEDIATELY)
                load_resource(r);
@@ -89,13 +102,13 @@ void ResourceManager::set_resource_location(Resource &r, const ResourceLocation
 
 const ResourceManager::ResourceLocation *ResourceManager::get_resource_location(const Resource &r) const
 {
-       const ManagedResource &managed = get_item(resources, &r);
+       const ManagedResource &managed = get_managed_resource(r);
        return managed.location.collection ? &managed.location : 0;
 }
 
 void ResourceManager::load_resource(Resource &r)
 {
-       ManagedResource &managed = get_item(resources, &r);
+       ManagedResource &managed = get_managed_resource(r);
        if(!managed.location.collection)
                throw runtime_error("no location");
 
@@ -105,13 +118,16 @@ void ResourceManager::load_resource(Resource &r)
        if(async_loads)
        {
                managed.state = ManagedResource::LOAD_QUEUED;
-               queue.push_back(&managed);
+               LoadQueue::iterator i;
+               for(i=queue.begin(); (i!=queue.end() && (*i)->load_priority>=managed.load_priority); ++i) ;
+               queue.insert(i, &managed);
        }
        else
        {
                managed.start_loading();
                while(!managed.loader->process()) ;
                managed.finish_loading(true);
+               total_data_size += managed.data_size;
        }
 }
 
@@ -136,7 +152,7 @@ void ResourceManager::resource_used(const Resource &r)
 
 void ResourceManager::remove_resource(Resource &r)
 {
-       ManagedResource &managed = get_item(resources, &r);
+       ManagedResource &managed = get_managed_resource(r);
        ManagedResource::State state = managed.state;
        if(state==ManagedResource::LOAD_QUEUED)
        {
@@ -146,17 +162,22 @@ void ResourceManager::remove_resource(Resource &r)
        }
        else if(state>ManagedResource::LOAD_QUEUED && state<ManagedResource::LOADED)
                thread.remove_resource(managed);
+
+       for(vector<ResourceObserver *>::const_iterator i=managed.observers.begin(); i!=managed.observers.end(); ++i)
+               (*i)->resource_removed(r);
+
+       MutexLock lock(map_mutex);
        remove_existing(resources, &r);
 }
 
-void ResourceManager::watch_resource(const Resource &r, ResourceWatcher &w)
+void ResourceManager::observe_resource(const Resource &r, ResourceObserver &w)
 {
-       get_item(resources, &r).add_watcher(w);
+       get_managed_resource(r).add_observer(w);
 }
 
-void ResourceManager::unwatch_resource(const Resource &r, ResourceWatcher &w)
+void ResourceManager::unobserve_resource(const Resource &r, ResourceObserver &w)
 {
-       get_item(resources, &r).remove_watcher(w);
+       get_managed_resource(r).remove_observer(w);
 }
 
 void ResourceManager::tick()
@@ -165,13 +186,17 @@ void ResourceManager::tick()
 
        bool do_unload = (frame>=next_unload);
        if(thread.sync())
+       {
+               total_data_size += thread.get_and_reset_loaded_data_size();
                do_unload = true;
+       }
 
        if(thread.needs_work() && !queue.empty())
                dispatch_work();
 
        if(do_unload)
        {
+               MutexLock lock(map_mutex);
                if(max_retain_frames && frame>=next_unload)
                {
                        unload_by_age();
@@ -214,14 +239,17 @@ void ResourceManager::unload_by_age()
 
        for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
                if(i->second.state==ManagedResource::LOADED && i->second.last_used<unload_limit)
+               {
                        i->second.unload();
+                       total_data_size -= i->second.data_size;
+               }
 }
 
 void ResourceManager::unload_by_size()
 {
        unsigned unload_limit = frame-min_retain_frames;
 
-       while(get_total_data_size()>size_limit)
+       while(total_data_size>size_limit)
        {
                ManagedResource *best = 0;
                UInt64 best_impact = 0;
@@ -240,18 +268,10 @@ void ResourceManager::unload_by_size()
                        break;
 
                best->unload();
+               total_data_size -= best->data_size;
        }
 }
 
-UInt64 ResourceManager::get_total_data_size() const
-{
-       UInt64 total = 0;
-       for(ResourceMap::const_iterator i=resources.begin(); i!=resources.end(); ++i)
-               if(i->second.state==ManagedResource::LOADED)
-                       total += i->second.data_size;
-       return total;
-}
-
 bool ResourceManager::age_order(ManagedResource *mr1, ManagedResource *mr2)
 {
        return mr1->last_used>mr2->last_used;
@@ -270,6 +290,7 @@ ResourceManager::ResourceLocation::ResourceLocation(DataFile::Collection &c, con
 
 ResourceManager::ManagedResource::ManagedResource(Resource &r):
        resource(&r),
+       load_priority(r.get_load_priority()),
        io(0),
        loader(0),
        state(NOT_LOADED),
@@ -283,7 +304,8 @@ void ResourceManager::ManagedResource::start_loading()
        if(!io)
                throw resource_load_error(location.name, "open failed");
 
-       loader = resource->load(*io);
+       const Resources *res = dynamic_cast<Resources *>(location.collection);
+       loader = resource->load(*io, res);
        if(!loader)
        {
                delete io;
@@ -314,7 +336,7 @@ void ResourceManager::ManagedResource::finish_loading(bool successful)
                state = LOADED;
                data_size = resource->get_data_size();
 
-               for(vector<ResourceWatcher *>::const_iterator i=watchers.begin(); i!=watchers.end(); ++i)
+               for(vector<ResourceObserver *>::const_iterator i=observers.begin(); i!=observers.end(); ++i)
                        (*i)->resource_loaded(*resource);
        }
        else
@@ -334,21 +356,21 @@ void ResourceManager::ManagedResource::unload()
        resource->unload();
        state = NOT_LOADED;
 
-       for(vector<ResourceWatcher *>::const_iterator i=watchers.begin(); i!=watchers.end(); ++i)
+       for(vector<ResourceObserver *>::const_iterator i=observers.begin(); i!=observers.end(); ++i)
                (*i)->resource_unloaded(*resource);
 }
 
-void ResourceManager::ManagedResource::add_watcher(ResourceWatcher &w)
+void ResourceManager::ManagedResource::add_observer(ResourceObserver &w)
 {
-       if(find(watchers.begin(), watchers.end(), &w)==watchers.end())
-               watchers.push_back(&w);
+       if(find(observers.begin(), observers.end(), &w)==observers.end())
+               observers.push_back(&w);
 }
 
-void ResourceManager::ManagedResource::remove_watcher(ResourceWatcher &w)
+void ResourceManager::ManagedResource::remove_observer(ResourceObserver &w)
 {
-       vector<ResourceWatcher *>::iterator end = remove(watchers.begin(), watchers.end(), &w);
-       if(end!=watchers.end())
-               watchers.erase(end, watchers.end());
+       vector<ResourceObserver *>::iterator end = remove(observers.begin(), observers.end(), &w);
+       if(end!=observers.end())
+               observers.erase(end, observers.end());
 }
 
 
@@ -356,6 +378,7 @@ ResourceManager::LoadingThread::LoadingThread():
        sem(1),
        capacity(2),
        size(0),
+       loaded_data_size(0),
        done(false)
 {
        launch();
@@ -391,13 +414,13 @@ void ResourceManager::LoadingThread::main()
        }
 }
 
-ResourceManager::ManagedResource *ResourceManager::LoadingThread::front(LoadQueue &queue)
+ResourceManager::ManagedResource *ResourceManager::LoadingThread::front(LoadQueue &que)
 {
        MutexLock lock(queue_mutex);
-       if(queue.empty())
+       if(que.empty())
                return 0;
 
-       return queue.front();
+       return que.front();
 }
 
 void ResourceManager::LoadingThread::add_resource(ManagedResource &r)
@@ -424,6 +447,11 @@ void ResourceManager::LoadingThread::remove_resource(ManagedResource &r)
                Time::sleep(Time::msec);
 
        r.finish_loading();
+       if(r.state==ManagedResource::LOADED)
+       {
+               MutexLock lock(data_size_mutex);
+               loaded_data_size += r.data_size;
+       }
 }
 
 bool ResourceManager::LoadingThread::try_remove_resource(ManagedResource &r)
@@ -435,12 +463,18 @@ bool ResourceManager::LoadingThread::try_remove_resource(ManagedResource &r)
        {
                i = find(sync_queue.begin(), sync_queue.end(), &r);
                if(i!=sync_queue.end())
+               {
                        sync_queue.erase(i);
+                       --size;
+               }
        }
        else if(i==async_queue.begin())
                return false;
        else
+       {
                async_queue.erase(i);
+               --size;
+       }
 
        return true;
 }
@@ -470,6 +504,11 @@ bool ResourceManager::LoadingThread::sync()
                if(managed->state==ManagedResource::LOAD_ERROR || managed->process(true))
                {
                        managed->finish_loading();
+                       if(managed->state==ManagedResource::LOADED)
+                       {
+                               MutexLock lock(data_size_mutex);
+                               loaded_data_size += managed->data_size;
+                       }
                        any_finished = true;
                        --size;
 
@@ -489,6 +528,14 @@ bool ResourceManager::LoadingThread::sync()
        return any_finished;
 }
 
+UInt64 ResourceManager::LoadingThread::get_and_reset_loaded_data_size()
+{
+       MutexLock lock(data_size_mutex);
+       UInt64 result = loaded_data_size;
+       loaded_data_size = 0;
+       return result;
+}
+
 void ResourceManager::LoadingThread::terminate()
 {
        done = true;