|
@@ -34,16 +34,17 @@ namespace CamelotEngine
|
|
|
{
|
|
{
|
|
|
ResourceLoadRequestPtr resRequest = boost::any_cast<ResourceLoadRequestPtr>(res->getRequest()->getData());
|
|
ResourceLoadRequestPtr resRequest = boost::any_cast<ResourceLoadRequestPtr>(res->getRequest()->getData());
|
|
|
|
|
|
|
|
- auto iterFind = gResources().mInProgressResources.find(resRequest->resource.getUUID());
|
|
|
|
|
- gResources().mInProgressResources.erase(iterFind);
|
|
|
|
|
-
|
|
|
|
|
if(res->getRequest()->getAborted())
|
|
if(res->getRequest()->getAborted())
|
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
|
|
+ gResources().notifyResourceLoadingFinished(resRequest->resource);
|
|
|
|
|
+
|
|
|
if(res->succeeded())
|
|
if(res->succeeded())
|
|
|
{
|
|
{
|
|
|
ResourceLoadResponsePtr resResponse = boost::any_cast<ResourceLoadResponsePtr>(res->getData());
|
|
ResourceLoadResponsePtr resResponse = boost::any_cast<ResourceLoadResponsePtr>(res->getData());
|
|
|
|
|
|
|
|
|
|
+ // This should be thread safe without any sync primitives, if other threads read a few cycles out of date value
|
|
|
|
|
+ // and think this resource isn't created when it really is, it hardly makes any difference
|
|
|
resRequest->resource.resolve(resResponse->rawResource);
|
|
resRequest->resource.resolve(resResponse->rawResource);
|
|
|
|
|
|
|
|
if(!gResources().metaExists_UUID(resResponse->rawResource->getUUID()))
|
|
if(!gResources().metaExists_UUID(resResponse->rawResource->getUUID()))
|
|
@@ -52,7 +53,7 @@ namespace CamelotEngine
|
|
|
gResources().addMetaData(resResponse->rawResource->getUUID(), resRequest->filePath);
|
|
gResources().addMetaData(resResponse->rawResource->getUUID(), resRequest->filePath);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- gResources().mLoadedResources[resResponse->rawResource->getUUID()] = resRequest->resource;
|
|
|
|
|
|
|
+ gResources().notifyNewResourceLoaded(resRequest->resource);
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
@@ -107,11 +108,6 @@ namespace CamelotEngine
|
|
|
delete mResponseHandler;
|
|
delete mResponseHandler;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void Resources::update()
|
|
|
|
|
- {
|
|
|
|
|
- mWorkQueue->processResponses();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
BaseResourceHandle Resources::load(const String& filePath)
|
|
BaseResourceHandle Resources::load(const String& filePath)
|
|
|
{
|
|
{
|
|
|
return loadInternal(filePath, true);
|
|
return loadInternal(filePath, true);
|
|
@@ -162,24 +158,38 @@ namespace CamelotEngine
|
|
|
|
|
|
|
|
String uuid = getUUIDFromPath(filePath);
|
|
String uuid = getUUIDFromPath(filePath);
|
|
|
|
|
|
|
|
- auto iterFind = mLoadedResources.find(uuid);
|
|
|
|
|
- if(iterFind != mLoadedResources.end()) // Resource is already loaded
|
|
|
|
|
{
|
|
{
|
|
|
- return iterFind->second;
|
|
|
|
|
|
|
+ CM_LOCK_MUTEX(mLoadedResourceMutex);
|
|
|
|
|
+ auto iterFind = mLoadedResources.find(uuid);
|
|
|
|
|
+ if(iterFind != mLoadedResources.end()) // Resource is already loaded
|
|
|
|
|
+ {
|
|
|
|
|
+ return iterFind->second;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- auto iterFind2 = mInProgressResources.find(uuid);
|
|
|
|
|
- if(iterFind2 != mInProgressResources.end()) // We're already loading this resource
|
|
|
|
|
|
|
+ bool resourceLoadingInProgress = false;
|
|
|
|
|
+ BaseResourceHandle existingResource;
|
|
|
|
|
+
|
|
|
{
|
|
{
|
|
|
- ResourceAsyncOp& asyncOp = iterFind2->second;
|
|
|
|
|
|
|
+ CM_LOCK_MUTEX(mInProgressResourcesMutex);
|
|
|
|
|
+ auto iterFind2 = mInProgressResources.find(uuid);
|
|
|
|
|
+ if(iterFind2 != mInProgressResources.end())
|
|
|
|
|
+ {
|
|
|
|
|
+ existingResource = iterFind2->second.resource;
|
|
|
|
|
+ resourceLoadingInProgress = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ if(resourceLoadingInProgress) // We're already loading this resource
|
|
|
|
|
+ {
|
|
|
if(!synchronous)
|
|
if(!synchronous)
|
|
|
- return asyncOp.resource;
|
|
|
|
|
|
|
+ return existingResource;
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- // It's already being loaded asynchronously but we want it right away,
|
|
|
|
|
- // so abort the async operation and load it right away.
|
|
|
|
|
- mWorkQueue->abortRequest(asyncOp.requestID);
|
|
|
|
|
|
|
+ // Previously being loaded as async but now we want it synced, so we wait
|
|
|
|
|
+ existingResource.waitUntilLoaded();
|
|
|
|
|
+
|
|
|
|
|
+ return existingResource;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -201,7 +211,10 @@ namespace CamelotEngine
|
|
|
newAsyncOp.resource = newResource;
|
|
newAsyncOp.resource = newResource;
|
|
|
newAsyncOp.requestID = requestId;
|
|
newAsyncOp.requestID = requestId;
|
|
|
|
|
|
|
|
- mInProgressResources[uuid] = newAsyncOp;
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ CM_LOCK_MUTEX(mInProgressResourcesMutex);
|
|
|
|
|
+ mInProgressResources[uuid] = newAsyncOp;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
mWorkQueue->addRequest(mWorkQueueChannel, resRequest, 0, synchronous);
|
|
mWorkQueue->addRequest(mWorkQueueChannel, resRequest, 0, synchronous);
|
|
|
return newResource;
|
|
return newResource;
|
|
@@ -229,17 +242,23 @@ namespace CamelotEngine
|
|
|
|
|
|
|
|
resource->destroy();
|
|
resource->destroy();
|
|
|
|
|
|
|
|
- mLoadedResources.erase(resource.getUUID());
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ CM_LOCK_MUTEX(mLoadedResourceMutex);
|
|
|
|
|
+ mLoadedResources.erase(resource.getUUID());
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Resources::unloadAllUnused()
|
|
void Resources::unloadAllUnused()
|
|
|
{
|
|
{
|
|
|
vector<BaseResourceHandle>::type resourcesToUnload;
|
|
vector<BaseResourceHandle>::type resourcesToUnload;
|
|
|
|
|
|
|
|
- for(auto iter = mLoadedResources.begin(); iter != mLoadedResources.end(); ++iter)
|
|
|
|
|
{
|
|
{
|
|
|
- if(iter->second.getInternalPtr().unique()) // We just have this one reference, meaning nothing is using this resource
|
|
|
|
|
- resourcesToUnload.push_back(iter->second);
|
|
|
|
|
|
|
+ CM_LOCK_MUTEX(mLoadedResourceMutex);
|
|
|
|
|
+ for(auto iter = mLoadedResources.begin(); iter != mLoadedResources.end(); ++iter)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(iter->second.getInternalPtr().unique()) // We just have this one reference, meaning nothing is using this resource
|
|
|
|
|
+ resourcesToUnload.push_back(iter->second);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
for(auto iter = resourcesToUnload.begin(); iter != resourcesToUnload.end(); ++iter)
|
|
for(auto iter = resourcesToUnload.begin(); iter != resourcesToUnload.end(); ++iter)
|
|
@@ -277,7 +296,11 @@ namespace CamelotEngine
|
|
|
|
|
|
|
|
save(resource);
|
|
save(resource);
|
|
|
|
|
|
|
|
- mLoadedResources[resource->getUUID()] = resource;
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ CM_LOCK_MUTEX(mLoadedResourceMutex);
|
|
|
|
|
+
|
|
|
|
|
+ mLoadedResources[resource->getUUID()] = resource;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Resources::save(BaseResourceHandle resource)
|
|
void Resources::save(BaseResourceHandle resource)
|
|
@@ -402,6 +425,20 @@ namespace CamelotEngine
|
|
|
return findIter != mResourceMetaData_FilePath.end();
|
|
return findIter != mResourceMetaData_FilePath.end();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ void Resources::notifyResourceLoadingFinished(BaseResourceHandle& handle)
|
|
|
|
|
+ {
|
|
|
|
|
+ CM_LOCK_MUTEX(mInProgressResourcesMutex);
|
|
|
|
|
+
|
|
|
|
|
+ mInProgressResources.erase(handle.getUUID());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void Resources::notifyNewResourceLoaded(BaseResourceHandle& handle)
|
|
|
|
|
+ {
|
|
|
|
|
+ CM_LOCK_MUTEX(mLoadedResourceMutex);
|
|
|
|
|
+
|
|
|
|
|
+ mLoadedResources[handle.getUUID()] = handle;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
CM_EXPORT Resources& gResources()
|
|
CM_EXPORT Resources& gResources()
|
|
|
{
|
|
{
|
|
|
return Resources::instance();
|
|
return Resources::instance();
|