X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fresourcemanager.cpp;h=52e5866a6aa887ce536d704f528dfbc5051f06cf;hb=5ef508ffc324d4f00239555c0566e4c1f2c9c5c4;hp=c6e3f357b9ce67b6f72fef04f30b5ff5e96483ab;hpb=508319df28270eccdfa03a880a8604549278a139;p=libs%2Fgl.git diff --git a/source/resourcemanager.cpp b/source/resourcemanager.cpp index c6e3f357..52e5866a 100644 --- a/source/resourcemanager.cpp +++ b/source/resourcemanager.cpp @@ -4,6 +4,7 @@ #include #include #include "resourcemanager.h" +#include "resources.h" #include "resourcewatcher.h" using namespace std; @@ -11,6 +12,10 @@ using namespace std; namespace Msp { namespace GL { +resource_load_error::resource_load_error(const string &name, const string &err): + runtime_error(format("%s: %s", name, err)) +{ } + 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())) { } @@ -61,28 +66,49 @@ 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 +{ + MutexLock lock(map_mutex); + return get_item(resources, &r); +} + +ResourceManager::ManagedResource &ResourceManager::get_managed_resource(const Resource &r) { - return &get_item(resources, &r); + MutexLock lock(map_mutex); + 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; + set_resource_location(r, ResourceLocation(c, n)); +} + +void ResourceManager::set_resource_location(Resource &r, const ResourceLocation &l) +{ + { + MutexLock lock(map_mutex); + 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_managed_resource(r); + return managed.location.collection ? &managed.location : 0; +} + void ResourceManager::load_resource(Resource &r) { - ManagedResource &managed = get_item(resources, &r); - if(!managed.collection) + ManagedResource &managed = get_managed_resource(r); + if(!managed.location.collection) throw runtime_error("no location"); if(managed.state!=ManagedResource::NOT_LOADED) @@ -91,7 +117,9 @@ 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 { @@ -101,9 +129,17 @@ void ResourceManager::load_resource(Resource &r) } } +bool ResourceManager::is_resource_loaded(const Resource &r) const +{ + ManagedResource *managed = reinterpret_cast(r.get_manager_data()); + return managed ? managed->state==ManagedResource::LOADED : false; +} + void ResourceManager::resource_used(const Resource &r) { ManagedResource *managed = reinterpret_cast(r.get_manager_data()); + if(!managed) + return; if(managed->state==ManagedResource::NOT_LOADED && policy!=LOAD_MANUALLY) load_resource(*managed->resource); @@ -114,7 +150,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) { @@ -124,17 +160,19 @@ void ResourceManager::remove_resource(Resource &r) } else if(state>ManagedResource::LOAD_QUEUED && state=next_unload) { unload_by_age(); @@ -199,7 +238,7 @@ void ResourceManager::unload_by_size() { unsigned unload_limit = frame-min_retain_frames; - while(get_total_data_size()>size_limit) + while(get_total_data_size_()>size_limit) { ManagedResource *best = 0; UInt64 best_impact = 0; @@ -221,7 +260,7 @@ void ResourceManager::unload_by_size() } } -UInt64 ResourceManager::get_total_data_size() const +UInt64 ResourceManager::get_total_data_size_() const { UInt64 total = 0; for(ResourceMap::const_iterator i=resources.begin(); i!=resources.end(); ++i) @@ -230,15 +269,31 @@ UInt64 ResourceManager::get_total_data_size() const return total; } +UInt64 ResourceManager::get_total_data_size() const +{ + MutexLock lock(map_mutex); + return get_total_data_size_(); +} + 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), - collection(0), + load_priority(r.get_load_priority()), io(0), loader(0), state(NOT_LOADED), @@ -248,8 +303,12 @@ ResourceManager::ManagedResource::ManagedResource(Resource &r): void ResourceManager::ManagedResource::start_loading() { - io = collection->open_raw(name); - loader = resource->load(*io); + io = location.collection->open_raw(location.name); + if(!io) + throw resource_load_error(location.name, "open failed"); + + const Resources *res = dynamic_cast(location.collection); + loader = resource->load(*io, res); if(!loader) { delete io; @@ -344,7 +403,7 @@ void ResourceManager::LoadingThread::main() catch(const exception &e) { MutexLock lock(queue_mutex); - error_queue.push_back(resource_load_error(managed->name, e)); + error_queue.push_back(resource_load_error(managed->location.name, e)); managed->state = ManagedResource::LOAD_ERROR; } @@ -401,12 +460,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; }