X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fresourcemanager.cpp;h=4b72685d4d4ba6f4594a2349101cc253b9ecd36f;hp=999b86c190451dae5a8d33967a3c461c5282862c;hb=HEAD;hpb=24a5a7e6dced2dbb44be06ca821e9600306b0bfd diff --git a/source/resourcemanager.cpp b/source/resourcemanager.cpp deleted file mode 100644 index 999b86c1..00000000 --- a/source/resourcemanager.cpp +++ /dev/null @@ -1,341 +0,0 @@ -#include -#include -#include "resourcemanager.h" -#include "resourcewatcher.h" - -using namespace std; - -namespace Msp { -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) -{ } - -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) -{ - ManagedResource &managed = get_item(resources, &r); - managed.collection = &c; - managed.name = n; - - if(policy==LOAD_IMMEDIATELY) - load_resource(r); -} - -void ResourceManager::load_resource(Resource &r) -{ - ManagedResource &managed = get_item(resources, &r); - if(!managed.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(); - } -} - -void ResourceManager::resource_used(const Resource &r) -{ - ManagedResource *managed = reinterpret_cast(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; -} - -void ResourceManager::remove_resource(Resource &r) -{ - ManagedResource *loading = thread.get_resource(); - if(loading && loading->resource==&r) - thread.set_resource(0); - - 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() -{ - LoadingThread::State thread_state = thread.get_state(); - bool check_total_size = false; - if(thread_state==LoadingThread::SYNC_PENDING || thread_state==LoadingThread::LOAD_FINISHED) - { - thread.sync(); - check_total_size = true; - } - else if(thread_state==LoadingThread::IDLE && !queue.empty()) - { - ManagedResource *managed = queue.front(); - 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.state==ManagedResource::LOADED) - { - if(i->second.last_used<=unload_limit) - i->second.unload(); - else if(!next_unload || i->second.last_usedsecond.last_used; - } - - 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.state==ManagedResource::LOADED && i->second.last_usedsecond.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; -} - - -ResourceManager::ManagedResource::ManagedResource(Resource &r): - resource(&r), - collection(0), - io(0), - loader(0), - state(NOT_LOADED), - last_used(0), - data_size(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"); - } - state = LOADING; -} - -void ResourceManager::ManagedResource::finish_loading() -{ - delete loader; - loader = 0; - state = LOADED; - delete io; - io = 0; - data_size = resource->get_data_size(); - - for(vector::const_iterator i=watchers.begin(); i!=watchers.end(); ++i) - (*i)->resource_loaded(*resource); -} - -void ResourceManager::ManagedResource::unload() -{ - resource->unload(); - state = NOT_LOADED; - - for(vector::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::iterator end = remove(watchers.begin(), watchers.end(), &w); - if(end!=watchers.end()) - watchers.erase(end, watchers.end()); -} - - -ResourceManager::LoadingThread::LoadingThread(ResourceManager &m): - manager(m), - sem(1), - resource(0), - state(IDLE) -{ - launch(); -} - -void ResourceManager::LoadingThread::main() -{ - while(state!=TERMINATING) - { - sem.wait(); - - if(state==BUSY) - { - Resource::AsyncLoader *ldr = resource->loader; - bool finished = false; - while(!finished && !ldr->needs_sync()) - finished = ldr->process(); - - if(finished) - state = LOAD_FINISHED; - else - state = SYNC_PENDING; - } - } -} - -void ResourceManager::LoadingThread::set_resource(ManagedResource *r) -{ - if(state!=IDLE) - { - while(state==BUSY) ; - // Force finish to clean up the loader - state = LOAD_FINISHED; - sync(); - } - - resource = r; - if(resource) - { - resource->start_loading(); - state = BUSY; - sem.signal(); - } -} - -void ResourceManager::LoadingThread::sync() -{ - State s = state; - bool finished = (s==LOAD_FINISHED); - if(s==SYNC_PENDING) - { - Resource::AsyncLoader *ldr = resource->loader; - while(!finished && ldr->needs_sync()) - finished = ldr->process(); - - if(!finished) - { - state = BUSY; - sem.signal(); - return; - } - } - - if(finished) - { - resource->finish_loading(); - resource = 0; - state = IDLE; - } -} - -void ResourceManager::LoadingThread::terminate() -{ - while(state==BUSY) ; - state = TERMINATING; - sem.signal(); - join(); -} - -} // namespace GL -} // namespace Msp