Commit 33aec2fc authored by David Reid's avatar David Reid

Clean up and bug fixes to the resource manager.

  * ma_resource_manager_uninit() has been implemented.
  * Bug fixes and inserting and removing data buffers from the BST.
  * Some old experimental code has been removed.
  * Minor whitespace clean up.
parent 005e19f7
...@@ -185,6 +185,7 @@ MA_API void ma_resource_manager_message_queue_uninit(ma_resource_manager_message ...@@ -185,6 +185,7 @@ MA_API void ma_resource_manager_message_queue_uninit(ma_resource_manager_message
MA_API ma_result ma_resource_manager_message_queue_post(ma_resource_manager_message_queue* pQueue, const ma_resource_manager_message* pMessage); MA_API ma_result ma_resource_manager_message_queue_post(ma_resource_manager_message_queue* pQueue, const ma_resource_manager_message* pMessage);
MA_API ma_result ma_resource_manager_message_queue_next(ma_resource_manager_message_queue* pQueue, ma_resource_manager_message* pMessage); /* Blocking */ MA_API ma_result ma_resource_manager_message_queue_next(ma_resource_manager_message_queue* pQueue, ma_resource_manager_message* pMessage); /* Blocking */
MA_API ma_result ma_resource_manager_message_queue_peek(ma_resource_manager_message_queue* pQueue, ma_resource_manager_message* pMessage); /* Non-Blocking */ MA_API ma_result ma_resource_manager_message_queue_peek(ma_resource_manager_message_queue* pQueue, ma_resource_manager_message* pMessage); /* Non-Blocking */
MA_API ma_result ma_resource_manager_message_queue_post_terminate(ma_resource_manager_message_queue* pQueue);
typedef struct typedef struct
...@@ -714,7 +715,6 @@ static ma_result ma_resource_manager_message_queue_post_nolock(ma_resource_manag ...@@ -714,7 +715,6 @@ static ma_result ma_resource_manager_message_queue_post_nolock(ma_resource_manag
} }
if (ma_resource_manager_message_queue_get_count(pQueue) == ma_countof(pQueue->messages)) { if (ma_resource_manager_message_queue_get_count(pQueue) == ma_countof(pQueue->messages)) {
return MA_OUT_OF_MEMORY; /* The queue is already full. */ return MA_OUT_OF_MEMORY; /* The queue is already full. */
} }
...@@ -819,6 +819,12 @@ MA_API ma_result ma_resource_manager_message_queue_peek(ma_resource_manager_mess ...@@ -819,6 +819,12 @@ MA_API ma_result ma_resource_manager_message_queue_peek(ma_resource_manager_mess
return MA_SUCCESS; return MA_SUCCESS;
} }
MA_API ma_result ma_resource_manager_message_queue_post_terminate(ma_resource_manager_message_queue* pQueue)
{
ma_resource_manager_message message = ma_resource_manager_message_init(MA_MESSAGE_TERMINATE);
return ma_resource_manager_message_queue_post(pQueue, &message);
}
/* /*
...@@ -916,6 +922,8 @@ static ma_result ma_resource_manager_data_buffer_insert_at(ma_resource_manager* ...@@ -916,6 +922,8 @@ static ma_result ma_resource_manager_data_buffer_insert_at(ma_resource_manager*
} }
} }
pDataBuffer->pParent = pInsertPoint;
return MA_SUCCESS; return MA_SUCCESS;
} }
...@@ -999,6 +1007,8 @@ static ma_result ma_resource_manager_data_buffer_remove(ma_resource_manager* pRe ...@@ -999,6 +1007,8 @@ static ma_result ma_resource_manager_data_buffer_remove(ma_resource_manager* pRe
} }
} else { } else {
/* Node has one child - pChildHi != NULL. */ /* Node has one child - pChildHi != NULL. */
pDataBuffer->pChildHi->pParent = pDataBuffer->pParent;
if (pDataBuffer->pParent == NULL) { if (pDataBuffer->pParent == NULL) {
MA_ASSERT(pResourceManager->pRootDataBuffer == pDataBuffer); MA_ASSERT(pResourceManager->pRootDataBuffer == pDataBuffer);
pResourceManager->pRootDataBuffer = pDataBuffer->pChildHi; pResourceManager->pRootDataBuffer = pDataBuffer->pChildHi;
...@@ -1013,6 +1023,8 @@ static ma_result ma_resource_manager_data_buffer_remove(ma_resource_manager* pRe ...@@ -1013,6 +1023,8 @@ static ma_result ma_resource_manager_data_buffer_remove(ma_resource_manager* pRe
} else { } else {
if (pDataBuffer->pChildHi == NULL) { if (pDataBuffer->pChildHi == NULL) {
/* Node has one child - pChildLo != NULL. */ /* Node has one child - pChildLo != NULL. */
pDataBuffer->pChildLo->pParent = pDataBuffer->pParent;
if (pDataBuffer->pParent == NULL) { if (pDataBuffer->pParent == NULL) {
MA_ASSERT(pResourceManager->pRootDataBuffer == pDataBuffer); MA_ASSERT(pResourceManager->pRootDataBuffer == pDataBuffer);
pResourceManager->pRootDataBuffer = pDataBuffer->pChildLo; pResourceManager->pRootDataBuffer = pDataBuffer->pChildLo;
...@@ -1138,6 +1150,27 @@ static ma_result ma_resource_manager_data_buffer_decrement_ref(ma_resource_manag ...@@ -1138,6 +1150,27 @@ static ma_result ma_resource_manager_data_buffer_decrement_ref(ma_resource_manag
static void ma_resource_manager_data_buffer_free(ma_resource_manager* pResourceManager, ma_resource_manager_data_buffer* pDataBuffer)
{
MA_ASSERT(pResourceManager != NULL);
MA_ASSERT(pDataBuffer != NULL);
if (pDataBuffer->data.type == ma_resource_manager_data_buffer_type_encoded) {
ma__free_from_callbacks((void*)pDataBuffer->data.encoded.pData, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_ENCODED_BUFFER*/);
pDataBuffer->data.encoded.pData = NULL;
pDataBuffer->data.encoded.sizeInBytes = 0;
} else {
ma__free_from_callbacks((void*)pDataBuffer->data.decoded.pData, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_DECODED_BUFFER*/);
pDataBuffer->data.decoded.pData = NULL;
pDataBuffer->data.decoded.frameCount = 0;
}
/* The data buffer itself needs to be freed. */
ma__free_from_callbacks(pDataBuffer, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_RESOURCE_MANAGER_DATA_BUFFER*/);
}
static ma_thread_result MA_THREADCALL ma_resource_manager_resource_thread(void* pUserData) static ma_thread_result MA_THREADCALL ma_resource_manager_resource_thread(void* pUserData)
...@@ -1235,13 +1268,39 @@ MA_API ma_result ma_resource_manager_init(const ma_resource_manager_config* pCon ...@@ -1235,13 +1268,39 @@ MA_API ma_result ma_resource_manager_init(const ma_resource_manager_config* pCon
return MA_SUCCESS; return MA_SUCCESS;
} }
static void ma_resource_manager_delete_all_data_buffers(ma_resource_manager* pResourceManager)
{
MA_ASSERT(pResourceManager);
/* If everything was done properly, there shouldn't be any active data buffers. */
while (pResourceManager->pRootDataBuffer != NULL) {
ma_resource_manager_data_buffer* pDataBuffer = pResourceManager->pRootDataBuffer;
ma_resource_manager_data_buffer_remove(pResourceManager, pDataBuffer);
/* The data buffer has been removed from the BST, so now we need to free it's data. */
ma_resource_manager_data_buffer_free(pResourceManager, pDataBuffer);
}
}
MA_API void ma_resource_manager_uninit(ma_resource_manager* pResourceManager) MA_API void ma_resource_manager_uninit(ma_resource_manager* pResourceManager)
{ {
if (pResourceManager == NULL) { if (pResourceManager == NULL) {
return; return;
} }
/* TODO: Need to delete all data buffers and free all of their memory. */ /* The async threads need to be killed first. To do this we need to post a termination message to the message queue and then wait for the thread. */
ma_resource_manager_message_queue_post_terminate(&pResourceManager->messageQueue);
ma_thread_wait(&pResourceManager->asyncThread);
/* At this point the thread should have returned and no other thread should be accessing our data. We can now delete all data buffers. */
ma_resource_manager_delete_all_data_buffers(pResourceManager);
/* The message queue is no longer needed. */
ma_resource_manager_message_queue_uninit(&pResourceManager->messageQueue);
/* We're no longer doing anything with data buffers so the lock can now be uninitialized. */
ma_mutex_uninit(&pResourceManager->dataBufferLock);
} }
...@@ -1369,7 +1428,6 @@ MA_API ma_result ma_resource_manager_create_data_buffer(ma_resource_manager* pRe ...@@ -1369,7 +1428,6 @@ MA_API ma_result ma_resource_manager_create_data_buffer(ma_resource_manager* pRe
return result; return result;
} }
static ma_result ma_resource_manager_delete_data_buffer_nolock(ma_resource_manager* pResourceManager, ma_resource_manager_data_buffer* pDataBuffer) static ma_result ma_resource_manager_delete_data_buffer_nolock(ma_resource_manager* pResourceManager, ma_resource_manager_data_buffer* pDataBuffer)
{ {
ma_uint32 result; ma_uint32 result;
...@@ -1507,44 +1565,6 @@ MA_API ma_result ma_resource_manager_unregister_data(ma_resource_manager* pResou ...@@ -1507,44 +1565,6 @@ MA_API ma_result ma_resource_manager_unregister_data(ma_resource_manager* pResou
} }
#if 0
static ma_result ma_resource_manager_data_source_hold(ma_resource_manager_data_source* pDataSource)
{
MA_ASSERT(pDataSource != NULL);
/* Don't allow holding if the data source is being deleted. */
if (pDataSource->result == MA_UNAVAILABLE) {
return MA_UNAVAILABLE;
}
ma_atomic_increment_32(&pDataSource->holdCount);
/* If while we were incrementing the hold count we became unavailble we need to abort. */
if (pDataSource->result == MA_UNAVAILABLE) {
ma_atomic_decrement_32(&pDataSource->holdCount);
return MA_UNAVAILABLE;
}
return MA_SUCCESS;
}
static ma_result ma_resource_manager_data_source_release(ma_resource_manager_data_source* pDataSource)
{
ma_uint32 newCount;
MA_ASSERT(pDataSource != NULL);
/* Note: Don't check for MA_UNAVAILABLE in this case because it's possible to be calling this just after the the data source has been uninitialized from another thread. */
newCount = ma_atomic_decrement_32(&pDataSource->holdCount);
if (newCount == 0xFFFFFFFF) {
MA_ASSERT(MA_FALSE); /* <-- If you hit this it means you have a hold/release mismatch. */
ma_atomic_exchange_32(&pDataSource->holdCount, 0);
return MA_INVALID_ARGS;
}
return MA_SUCCESS;
}
#endif
static ma_bool32 ma_resource_manager_data_source_is_busy(ma_resource_manager_data_source* pDataSource, ma_uint64 requiredFrameCount) static ma_bool32 ma_resource_manager_data_source_is_busy(ma_resource_manager_data_source* pDataSource, ma_uint64 requiredFrameCount)
...@@ -1977,13 +1997,6 @@ MA_API ma_result ma_resource_manager_data_source_uninit(ma_resource_manager* pRe ...@@ -1977,13 +1997,6 @@ MA_API ma_result ma_resource_manager_data_source_uninit(ma_resource_manager* pRe
/* The first thing to do is to mark the data source as unavailable. This will stop other threads from acquiring a hold on the data source which is what happens in the callbacks. */ /* The first thing to do is to mark the data source as unavailable. This will stop other threads from acquiring a hold on the data source which is what happens in the callbacks. */
ma_atomic_exchange_32(&pDataSource->result, MA_UNAVAILABLE); ma_atomic_exchange_32(&pDataSource->result, MA_UNAVAILABLE);
#if 0
/* Wait for everything to release the data source. This should be a short hold so just spin. The audio thread might be in the middle of reading data from the data source. */
while (pDataSource->holdCount > 0) {
ma_yield();
}
#endif
/* We should uninitialize the data source's backend before deleting the data buffer just to keep the order of operations clean. */ /* We should uninitialize the data source's backend before deleting the data buffer just to keep the order of operations clean. */
ma_resource_manager_data_source_uninit_backend_buffer(pResourceManager, pDataSource); ma_resource_manager_data_source_uninit_backend_buffer(pResourceManager, pDataSource);
pDataSource->type = ma_resource_manager_data_source_type_unknown; pDataSource->type = ma_resource_manager_data_source_type_unknown;
...@@ -2204,18 +2217,7 @@ static ma_result ma_resource_manager_handle_message__free_data_buffer(ma_resourc ...@@ -2204,18 +2217,7 @@ static ma_result ma_resource_manager_handle_message__free_data_buffer(ma_resourc
MA_ASSERT(pDataBuffer->result == MA_UNAVAILABLE); MA_ASSERT(pDataBuffer->result == MA_UNAVAILABLE);
if (pDataBuffer->data.type == ma_resource_manager_data_buffer_type_encoded) { ma_resource_manager_data_buffer_free(pResourceManager, pDataBuffer);
ma__free_from_callbacks((void*)pDataBuffer->data.encoded.pData, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_ENCODED_BUFFER*/);
pDataBuffer->data.encoded.pData = NULL;
pDataBuffer->data.encoded.sizeInBytes = 0;
} else {
ma__free_from_callbacks((void*)pDataBuffer->data.decoded.pData, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_DECODED_BUFFER*/);
pDataBuffer->data.decoded.pData = NULL;
pDataBuffer->data.decoded.frameCount = 0;
}
/* The data buffer itself needs to be freed. */
ma__free_from_callbacks(pDataBuffer, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_RESOURCE_MANAGER_DATA_BUFFER*/);
return MA_SUCCESS; return MA_SUCCESS;
} }
......
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