mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-24 09:14:04 +02:00
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.
This commit is contained in:
+62
-60
@@ -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
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|||||||
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*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
|||||||
}
|
}
|
||||||
} 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
|
|||||||
} 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
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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
|
|||||||
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
|
|||||||
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#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
|
|||||||
/* 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
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user