]> git.tdb.fi Git - libs/gl.git/blobdiff - source/resourcemanager.cpp
Check the flat qualifier from the correct member
[libs/gl.git] / source / resourcemanager.cpp
diff --git a/source/resourcemanager.cpp b/source/resourcemanager.cpp
deleted file mode 100644 (file)
index 40dcff9..0000000
+++ /dev/null
@@ -1,493 +0,0 @@
-#include <algorithm>
-#include <typeinfo>
-#include <msp/debug/demangle.h>
-#include <msp/strings/format.h>
-#include <msp/time/utils.h>
-#include "resourcemanager.h"
-#include "resourcewatcher.h"
-
-using namespace std;
-
-namespace Msp {
-namespace GL {
-
-resource_load_error::resource_load_error(const string &name, const exception &exc):
-       runtime_error(format("%s: %s: %s", name, Debug::demangle(typeid(exc).name()), exc.what()))
-{ }
-
-
-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)
-{ }
-
-ResourceManager::~ResourceManager()
-{
-       thread.terminate();
-
-       while(!resources.empty())
-               resources.begin()->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_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;
-}
-
-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)
-{
-       set_resource_location(r, ResourceLocation(c, n));
-}
-
-void ResourceManager::set_resource_location(Resource &r, const ResourceLocation &l)
-{
-       ManagedResource &managed = get_item(resources, &r);
-       managed.location = l;
-
-       if(policy==LOAD_IMMEDIATELY)
-               load_resource(r);
-}
-
-const ResourceManager::ResourceLocation *ResourceManager::get_resource_location(const Resource &r) const
-{
-       const ManagedResource &managed = get_item(resources, &r);
-       return managed.location.collection ? &managed.location : 0;
-}
-
-void ResourceManager::load_resource(Resource &r)
-{
-       ManagedResource &managed = get_item(resources, &r);
-       if(!managed.location.collection)
-               throw runtime_error("no location");
-
-       if(managed.state!=ManagedResource::NOT_LOADED)
-               return;
-
-       if(async_loads)
-       {
-               managed.state = ManagedResource::LOAD_QUEUED;
-               queue.push_back(&managed);
-       }
-       else
-       {
-               managed.start_loading();
-               while(!managed.loader->process()) ;
-               managed.finish_loading(true);
-       }
-}
-
-bool ResourceManager::is_resource_loaded(const Resource &r)
-{
-       ManagedResource *managed = reinterpret_cast<ManagedResource *>(r.get_manager_data());
-       return managed ? managed->state==ManagedResource::LOADED : false;
-}
-
-void ResourceManager::resource_used(const Resource &r)
-{
-       ManagedResource *managed = reinterpret_cast<ManagedResource *>(r.get_manager_data());
-       if(managed->state==ManagedResource::NOT_LOADED && policy!=LOAD_MANUALLY)
-               load_resource(*managed->resource);
-
-       managed->last_used = frame;
-       if(max_retain_frames && !next_unload)
-               next_unload = frame+max_retain_frames+1;
-}
-
-void ResourceManager::remove_resource(Resource &r)
-{
-       ManagedResource &managed = get_item(resources, &r);
-       ManagedResource::State state = managed.state;
-       if(state==ManagedResource::LOAD_QUEUED)
-       {
-               LoadQueue::iterator i = find(queue.begin(), queue.end(), &managed);
-               if(i!=queue.end())
-                       queue.erase(i);
-       }
-       else if(state>ManagedResource::LOAD_QUEUED && state<ManagedResource::LOADED)
-               thread.remove_resource(managed);
-       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()
-{
-       ++frame;
-
-       bool do_unload = (frame>=next_unload);
-       if(thread.sync())
-               do_unload = true;
-
-       if(thread.needs_work() && !queue.empty())
-               dispatch_work();
-
-       if(do_unload)
-       {
-               if(max_retain_frames && frame>=next_unload)
-               {
-                       unload_by_age();
-
-                       next_unload = frame;
-                       for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
-                               if(i->second.state==ManagedResource::LOADED)
-                                       next_unload = min(next_unload, i->second.last_used);
-                       next_unload = (next_unload<frame ? next_unload+max_retain_frames : 0);
-               }
-
-               if(size_limit)
-                       unload_by_size();
-       }
-}
-
-void ResourceManager::dispatch_work()
-{
-       queue.sort(age_order);
-
-       if(queue.front()->last_used+10<frame)
-       {
-               for(LoadQueue::iterator i=queue.begin(); i!=queue.end(); ++i)
-                       (*i)->state = ManagedResource::NOT_LOADED;
-               queue.clear();
-               return;
-       }
-
-       while(thread.needs_work() && !queue.empty())
-       {
-               ManagedResource *managed = queue.front();
-               queue.pop_front();
-               thread.add_resource(*managed);
-       }
-}
-
-void ResourceManager::unload_by_age()
-{
-       unsigned unload_limit = frame-max_retain_frames;
-
-       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();
-}
-
-void ResourceManager::unload_by_size()
-{
-       unsigned unload_limit = frame-min_retain_frames;
-
-       while(get_total_data_size()>size_limit)
-       {
-               ManagedResource *best = 0;
-               UInt64 best_impact = 0;
-               for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
-                       if(i->second.state==ManagedResource::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.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;
-}
-
-
-ResourceManager::ResourceLocation::ResourceLocation():
-       collection(0)
-{ }
-
-ResourceManager::ResourceLocation::ResourceLocation(DataFile::Collection &c, const string &n):
-       collection(&c),
-       name(n)
-{ }
-
-
-ResourceManager::ManagedResource::ManagedResource(Resource &r):
-       resource(&r),
-       io(0),
-       loader(0),
-       state(NOT_LOADED),
-       last_used(0),
-       data_size(0)
-{ }
-
-void ResourceManager::ManagedResource::start_loading()
-{
-       io = location.collection->open_raw(location.name);
-       loader = resource->load(*io);
-       if(!loader)
-       {
-               delete io;
-               io = 0;
-               throw logic_error("no loader created");
-       }
-       state = LOADING;
-}
-
-bool ResourceManager::ManagedResource::process(bool sync)
-{
-       while(state!=LOAD_FINISHED && loader->needs_sync()==sync)
-               if(loader->process())
-                       state = LOAD_FINISHED;
-
-       return state==LOAD_FINISHED;
-}
-
-void ResourceManager::ManagedResource::finish_loading(bool successful)
-{
-       delete loader;
-       loader = 0;
-       delete io;
-       io = 0;
-
-       if(successful)
-       {
-               state = LOADED;
-               data_size = resource->get_data_size();
-
-               for(vector<ResourceWatcher *>::const_iterator i=watchers.begin(); i!=watchers.end(); ++i)
-                       (*i)->resource_loaded(*resource);
-       }
-       else
-       {
-               resource->unload();
-               state = NOT_LOADED;
-       }
-}
-
-void ResourceManager::ManagedResource::finish_loading()
-{
-       finish_loading(state==LOAD_FINISHED);
-}
-
-void ResourceManager::ManagedResource::unload()
-{
-       resource->unload();
-       state = NOT_LOADED;
-
-       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());
-}
-
-
-ResourceManager::LoadingThread::LoadingThread():
-       sem(1),
-       capacity(2),
-       size(0),
-       done(false)
-{
-       launch();
-}
-
-void ResourceManager::LoadingThread::main()
-{
-       bool wait_for_work = false;
-       while(!done)
-       {
-               if(wait_for_work)
-                       sem.wait();
-
-               if(ManagedResource *managed = front(async_queue))
-               {
-                       try
-                       {
-                               managed->process(false);
-                       }
-                       catch(const exception &e)
-                       {
-                               MutexLock lock(queue_mutex);
-                               error_queue.push_back(resource_load_error(managed->location.name, e));
-                               managed->state = ManagedResource::LOAD_ERROR;
-                       }
-
-                       MutexLock lock(queue_mutex);
-                       sync_queue.splice(sync_queue.end(), async_queue, async_queue.begin());
-                       wait_for_work = async_queue.empty();
-               }
-               else
-                       wait_for_work = true;
-       }
-}
-
-ResourceManager::ManagedResource *ResourceManager::LoadingThread::front(LoadQueue &queue)
-{
-       MutexLock lock(queue_mutex);
-       if(queue.empty())
-               return 0;
-
-       return queue.front();
-}
-
-void ResourceManager::LoadingThread::add_resource(ManagedResource &r)
-{
-       r.start_loading();
-
-       MutexLock lock(queue_mutex);
-       if(r.loader->needs_sync())
-               sync_queue.push_back(&r);
-       else
-       {
-               bool was_empty = async_queue.empty();
-               async_queue.push_back(&r);
-               if(was_empty)
-                       sem.signal();
-       }
-
-       ++size;
-}
-
-void ResourceManager::LoadingThread::remove_resource(ManagedResource &r)
-{
-       while(!try_remove_resource(r))
-               Time::sleep(Time::msec);
-
-       r.finish_loading();
-}
-
-bool ResourceManager::LoadingThread::try_remove_resource(ManagedResource &r)
-{
-       MutexLock lock(queue_mutex);
-
-       LoadQueue::iterator i = find(async_queue.begin(), async_queue.end(), &r);
-       if(i==async_queue.end())
-       {
-               i = find(sync_queue.begin(), sync_queue.end(), &r);
-               if(i!=sync_queue.end())
-                       sync_queue.erase(i);
-       }
-       else if(i==async_queue.begin())
-               return false;
-       else
-               async_queue.erase(i);
-
-       return true;
-}
-
-bool ResourceManager::LoadingThread::sync()
-{
-       {
-               MutexLock lock(queue_mutex);
-
-               if(!error_queue.empty())
-               {
-                       resource_load_error err = error_queue.front();
-                       error_queue.pop_front();
-                       throw err;
-               }
-
-               unsigned async_size = async_queue.size();
-               if(async_size==0 && size==capacity)
-                       ++capacity;
-               else if(async_size>2 && capacity>2)
-                       --capacity;
-       }
-
-       bool any_finished = false;
-       while(ManagedResource *managed = front(sync_queue))
-       {
-               if(managed->state==ManagedResource::LOAD_ERROR || managed->process(true))
-               {
-                       managed->finish_loading();
-                       any_finished = true;
-                       --size;
-
-                       MutexLock lock(queue_mutex);
-                       sync_queue.pop_front();
-               }
-               else
-               {
-                       MutexLock lock(queue_mutex);
-                       bool was_empty = async_queue.empty();
-                       async_queue.splice(async_queue.end(), sync_queue, sync_queue.begin());
-                       if(was_empty)
-                               sem.signal();
-               }
-       }
-
-       return any_finished;
-}
-
-void ResourceManager::LoadingThread::terminate()
-{
-       done = true;
-       sem.signal();
-       join();
-       async_queue.clear();
-       sync_queue.clear();
-}
-
-} // namespace GL
-} // namespace Msp