Commit 6cdeaace authored by David Reid's avatar David Reid

Fix some bugs when acquiring a data buffer node.

parent ce86d631
...@@ -58768,48 +58768,10 @@ static ma_result ma_resource_manager_data_buffer_node_decode_next_page(ma_resour ...@@ -58768,48 +58768,10 @@ static ma_result ma_resource_manager_data_buffer_node_decode_next_page(ma_resour
return result; return result;
} }
static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manager* pResourceManager, const char* pFilePath, const wchar_t* pFilePathW, ma_uint32 hashedName32, ma_uint32 flags, const ma_resource_manager_data_supply* pExistingData, ma_fence* pInitFence, ma_fence* pDoneFence, ma_resource_manager_data_buffer_node** ppDataBufferNode) static ma_result ma_resource_manager_data_buffer_node_acquire_critical_section(ma_resource_manager* pResourceManager, const char* pFilePath, const wchar_t* pFilePathW, ma_uint32 hashedName32, ma_uint32 flags, const ma_resource_manager_data_supply* pExistingData, ma_fence* pInitFence, ma_fence* pDoneFence, ma_resource_manager_inline_notification* pInitNotification, ma_resource_manager_data_buffer_node** ppDataBufferNode)
{ {
ma_result result = MA_SUCCESS; ma_result result;
ma_bool32 nodeAlreadyExists = MA_FALSE;
ma_resource_manager_data_buffer_node* pDataBufferNode = NULL; ma_resource_manager_data_buffer_node* pDataBufferNode = NULL;
ma_resource_manager_inline_notification initNotification; /* Used when the WAIT_INIT flag is set. */
if (ppDataBufferNode != NULL) {
*ppDataBufferNode = NULL; /* Safety. */
}
if (pResourceManager == NULL || (pFilePath == NULL && pFilePathW == NULL && hashedName32 == 0)) {
return MA_INVALID_ARGS;
}
/* If we're specifying existing data, it must be valid. */
if (pExistingData != NULL && pExistingData->type == ma_resource_manager_data_supply_type_unknown) {
return MA_INVALID_ARGS;
}
/* If we don't support threading, remove the ASYNC flag to make the rest of this a bit simpler. */
if (ma_resource_manager_is_threading_enabled(pResourceManager) == MA_FALSE) {
flags &= ~MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC;
}
if (hashedName32 == 0) {
if (pFilePath != NULL) {
hashedName32 = ma_hash_string_32(pFilePath);
} else {
hashedName32 = ma_hash_string_w_32(pFilePathW);
}
}
/*
Here is where we either increment the node's reference count or allocate a new one and add it
to the BST. When allocating a new node, we need to make sure the LOAD_DATA_BUFFER_NODE job is
posted inside the critical section just in case the caller immediately uninitializes the node
as this will ensure the FREE_DATA_BUFFER_NODE job is given an execution order such that the
node is not uninitialized before initialization.
*/
ma_resource_manager_data_buffer_bst_lock(pResourceManager);
{
ma_resource_manager_data_buffer_node* pInsertPoint; ma_resource_manager_data_buffer_node* pInsertPoint;
result = ma_resource_manager_data_buffer_node_insert_point(pResourceManager, hashedName32, &pInsertPoint); result = ma_resource_manager_data_buffer_node_insert_point(pResourceManager, hashedName32, &pInsertPoint);
...@@ -58819,10 +58781,10 @@ static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manage ...@@ -58819,10 +58781,10 @@ static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manage
result = ma_resource_manager_data_buffer_node_increment_ref(pResourceManager, pDataBufferNode, NULL); result = ma_resource_manager_data_buffer_node_increment_ref(pResourceManager, pDataBufferNode, NULL);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
goto early_exit; /* Should never happen. Failed to increment the reference count. */ return result; /* Should never happen. Failed to increment the reference count. */
} }
nodeAlreadyExists = MA_TRUE; /* This is used later on, outside of this critical section, to determine whether or not a synchronous load should happen now. */ return MA_ALREADY_EXISTS; /* This is used later on, outside of the critical section, to determine whether or not a synchronous load should happen now. */
} else { } else {
/* /*
The node does not already exist. We need to post a LOAD_DATA_BUFFER_NODE job here. This The node does not already exist. We need to post a LOAD_DATA_BUFFER_NODE job here. This
...@@ -58831,8 +58793,7 @@ static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manage ...@@ -58831,8 +58793,7 @@ static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manage
*/ */
pDataBufferNode = (ma_resource_manager_data_buffer_node*)ma_malloc(sizeof(*pDataBufferNode), &pResourceManager->config.allocationCallbacks); pDataBufferNode = (ma_resource_manager_data_buffer_node*)ma_malloc(sizeof(*pDataBufferNode), &pResourceManager->config.allocationCallbacks);
if (pDataBufferNode == NULL) { if (pDataBufferNode == NULL) {
result = MA_OUT_OF_MEMORY; return MA_OUT_OF_MEMORY;
goto early_exit;
} }
MA_ZERO_OBJECT(pDataBufferNode); MA_ZERO_OBJECT(pDataBufferNode);
...@@ -58852,7 +58813,7 @@ static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manage ...@@ -58852,7 +58813,7 @@ static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manage
result = ma_resource_manager_data_buffer_node_insert_at(pResourceManager, pDataBufferNode, pInsertPoint); result = ma_resource_manager_data_buffer_node_insert_at(pResourceManager, pDataBufferNode, pInsertPoint);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_free(pDataBufferNode, &pResourceManager->config.allocationCallbacks); ma_free(pDataBufferNode, &pResourceManager->config.allocationCallbacks);
goto early_exit; /* Should never happen. Failed to insert the data buffer into the BST. */ return result; /* Should never happen. Failed to insert the data buffer into the BST. */
} }
/* /*
...@@ -58874,12 +58835,13 @@ static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manage ...@@ -58874,12 +58835,13 @@ static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manage
} }
if (pFilePathCopy == NULL && pFilePathWCopy == NULL) { if (pFilePathCopy == NULL && pFilePathWCopy == NULL) {
result = MA_OUT_OF_MEMORY; ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBufferNode);
goto done; ma_free(pDataBufferNode, &pResourceManager->config.allocationCallbacks);
return MA_OUT_OF_MEMORY;
} }
if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) { if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) {
ma_resource_manager_inline_notification_init(pResourceManager, &initNotification); ma_resource_manager_inline_notification_init(pResourceManager, pInitNotification);
} }
/* Acquire init and done fences before posting the job. These will be unacquired by the job thread. */ /* Acquire init and done fences before posting the job. These will be unacquired by the job thread. */
...@@ -58893,7 +58855,7 @@ static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manage ...@@ -58893,7 +58855,7 @@ static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manage
job.loadDataBufferNode.pFilePath = pFilePathCopy; job.loadDataBufferNode.pFilePath = pFilePathCopy;
job.loadDataBufferNode.pFilePathW = pFilePathWCopy; job.loadDataBufferNode.pFilePathW = pFilePathWCopy;
job.loadDataBufferNode.decode = (flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE ) != 0; job.loadDataBufferNode.decode = (flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE ) != 0;
job.loadDataBufferNode.pInitNotification = ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) ? &initNotification : NULL; job.loadDataBufferNode.pInitNotification = ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) ? pInitNotification : NULL;
job.loadDataBufferNode.pDoneNotification = NULL; job.loadDataBufferNode.pDoneNotification = NULL;
job.loadDataBufferNode.pInitFence = pInitFence; job.loadDataBufferNode.pInitFence = pInitFence;
job.loadDataBufferNode.pDoneFence = pDoneFence; job.loadDataBufferNode.pDoneFence = pDoneFence;
...@@ -58910,19 +58872,81 @@ static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manage ...@@ -58910,19 +58872,81 @@ static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manage
if (pInitFence != NULL) { ma_fence_release(pInitFence); } if (pInitFence != NULL) { ma_fence_release(pInitFence); }
if (pDoneFence != NULL) { ma_fence_release(pDoneFence); } if (pDoneFence != NULL) { ma_fence_release(pDoneFence); }
if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) {
ma_resource_manager_inline_notification_init(pResourceManager, pInitNotification);
}
ma_free(pFilePathCopy, &pResourceManager->config.allocationCallbacks); ma_free(pFilePathCopy, &pResourceManager->config.allocationCallbacks);
ma_free(pFilePathWCopy, &pResourceManager->config.allocationCallbacks); ma_free(pFilePathWCopy, &pResourceManager->config.allocationCallbacks);
goto done;
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBufferNode);
ma_free(pDataBufferNode, &pResourceManager->config.allocationCallbacks);
return result;
}
}
}
if (ppDataBufferNode != NULL) {
*ppDataBufferNode = pDataBufferNode;
} }
return MA_SUCCESS;
}
static ma_result ma_resource_manager_data_buffer_node_acquire(ma_resource_manager* pResourceManager, const char* pFilePath, const wchar_t* pFilePathW, ma_uint32 hashedName32, ma_uint32 flags, const ma_resource_manager_data_supply* pExistingData, ma_fence* pInitFence, ma_fence* pDoneFence, ma_resource_manager_data_buffer_node** ppDataBufferNode)
{
ma_result result = MA_SUCCESS;
ma_bool32 nodeAlreadyExists = MA_FALSE;
ma_resource_manager_data_buffer_node* pDataBufferNode = NULL;
ma_resource_manager_inline_notification initNotification; /* Used when the WAIT_INIT flag is set. */
if (ppDataBufferNode != NULL) {
*ppDataBufferNode = NULL; /* Safety. */
} }
if (pResourceManager == NULL || (pFilePath == NULL && pFilePathW == NULL && hashedName32 == 0)) {
return MA_INVALID_ARGS;
} }
/* If we're specifying existing data, it must be valid. */
if (pExistingData != NULL && pExistingData->type == ma_resource_manager_data_supply_type_unknown) {
return MA_INVALID_ARGS;
}
/* If we don't support threading, remove the ASYNC flag to make the rest of this a bit simpler. */
if (ma_resource_manager_is_threading_enabled(pResourceManager) == MA_FALSE) {
flags &= ~MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC;
}
if (hashedName32 == 0) {
if (pFilePath != NULL) {
hashedName32 = ma_hash_string_32(pFilePath);
} else {
hashedName32 = ma_hash_string_w_32(pFilePathW);
}
}
/*
Here is where we either increment the node's reference count or allocate a new one and add it
to the BST. When allocating a new node, we need to make sure the LOAD_DATA_BUFFER_NODE job is
posted inside the critical section just in case the caller immediately uninitializes the node
as this will ensure the FREE_DATA_BUFFER_NODE job is given an execution order such that the
node is not uninitialized before initialization.
*/
ma_resource_manager_data_buffer_bst_lock(pResourceManager);
{
result = ma_resource_manager_data_buffer_node_acquire_critical_section(pResourceManager, pFilePath, pFilePathW, hashedName32, flags, pExistingData, pInitFence, pDoneFence, &initNotification, &pDataBufferNode);
} }
ma_resource_manager_data_buffer_bst_unlock(pResourceManager); ma_resource_manager_data_buffer_bst_unlock(pResourceManager);
early_exit: if (result == MA_ALREADY_EXISTS) {
nodeAlreadyExists = MA_TRUE;
} else {
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; return result;
} }
}
/* /*
If we're loading synchronously, we'll need to load everything now. When loading asynchronously, If we're loading synchronously, we'll need to load everything now. When loading asynchronously,
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment