]> git.tdb.fi Git - libs/gl.git/blobdiff - source/resourcemanager.cpp
Throw a resource_load_error if the source could not be opened
[libs/gl.git] / source / resourcemanager.cpp
index 7bf4412f41c7bdbc7d372ab08aba0d9280f1cdfc..733cfaff8c4c37ba5ae1ffbd605ceb3f8d6a58df 100644 (file)
@@ -1,4 +1,7 @@
 #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"
@@ -8,6 +11,15 @@ 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()))
+{ }
+
+
 ResourceManager::ResourceManager():
        policy(LOAD_ON_DEMAND),
        async_loads(true),
@@ -62,19 +74,29 @@ void *ResourceManager::get_data_for_resource(const Resource &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.collection = &c;
-       managed.name = n;
+       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.collection)
+       if(!managed.location.collection)
                throw runtime_error("no location");
 
        if(managed.state!=ManagedResource::NOT_LOADED)
@@ -93,9 +115,17 @@ void ResourceManager::load_resource(Resource &r)
        }
 }
 
+bool ResourceManager::is_resource_loaded(const Resource &r) const
+{
+       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)
+               return;
        if(managed->state==ManagedResource::NOT_LOADED && policy!=LOAD_MANUALLY)
                load_resource(*managed->resource);
 
@@ -228,9 +258,18 @@ bool ResourceManager::age_order(ManagedResource *mr1, ManagedResource *mr2)
 }
 
 
+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),
        io(0),
        loader(0),
        state(NOT_LOADED),
@@ -240,7 +279,10 @@ ResourceManager::ManagedResource::ManagedResource(Resource &r):
 
 void ResourceManager::ManagedResource::start_loading()
 {
-       io = collection->open_raw(name);
+       io = location.collection->open_raw(location.name);
+       if(!io)
+               throw resource_load_error(location.name, "open failed");
+
        loader = resource->load(*io);
        if(!loader)
        {
@@ -329,7 +371,16 @@ void ResourceManager::LoadingThread::main()
 
                if(ManagedResource *managed = front(async_queue))
                {
-                       managed->process(false);
+                       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());
@@ -398,6 +449,14 @@ 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;
@@ -408,7 +467,7 @@ bool ResourceManager::LoadingThread::sync()
        bool any_finished = false;
        while(ManagedResource *managed = front(sync_queue))
        {
-               if(managed->process(true))
+               if(managed->state==ManagedResource::LOAD_ERROR || managed->process(true))
                {
                        managed->finish_loading();
                        any_finished = true;