Commit 8f40d5cd authored by David Reid's avatar David Reid

Fix an atomicity bug.

parent 3542cd26
...@@ -1312,7 +1312,7 @@ typedef enum ...@@ -1312,7 +1312,7 @@ typedef enum
typedef struct typedef struct
{ {
ma_decoded_data_supplier supplier; MA_ATOMIC ma_decoded_data_supplier supplier; /* Read and written from different threads so needs to be accessed atomically. */
const void* pData; /* Only used if `supplier` is ma_decoded_data_supplier_buffer. */ const void* pData; /* Only used if `supplier` is ma_decoded_data_supplier_buffer. */
ma_paged_audio_buffer_data pagedData; /* Only used if `supplier` is ma_decoded_data_supplier_paged. */ ma_paged_audio_buffer_data pagedData; /* Only used if `supplier` is ma_decoded_data_supplier_paged. */
ma_uint64 frameCount; /* The total number of PCM frames making up the decoded data. */ ma_uint64 frameCount; /* The total number of PCM frames making up the decoded data. */
...@@ -6156,6 +6156,16 @@ static ma_result ma_resource_manager_data_buffer_node_remove_by_key(ma_resource_ ...@@ -6156,6 +6156,16 @@ static ma_result ma_resource_manager_data_buffer_node_remove_by_key(ma_resource_
} }
#endif #endif
static ma_decoded_data_supplier ma_resource_manager_data_buffer_node_get_decoded_data_supplier(ma_resource_manager_data_buffer_node* pDataBufferNode)
{
return (ma_decoded_data_supplier)c89atomic_load_i32(&pDataBufferNode->data.decoded.supplier);
}
static void ma_resource_manager_data_buffer_node_set_decoded_data_supplier(ma_resource_manager_data_buffer_node* pDataBufferNode, ma_decoded_data_supplier supplier)
{
c89atomic_exchange_i32(&pDataBufferNode->data.decoded.supplier, supplier);
}
static ma_result ma_resource_manager_data_buffer_node_increment_ref(ma_resource_manager* pResourceManager, ma_resource_manager_data_buffer_node* pDataBufferNode, ma_uint32* pNewRefCount) static ma_result ma_resource_manager_data_buffer_node_increment_ref(ma_resource_manager* pResourceManager, ma_resource_manager_data_buffer_node* pDataBufferNode, ma_uint32* pNewRefCount)
{ {
ma_uint32 refCount; ma_uint32 refCount;
...@@ -6203,10 +6213,10 @@ static void ma_resource_manager_data_buffer_node_free(ma_resource_manager* pReso ...@@ -6203,10 +6213,10 @@ static void ma_resource_manager_data_buffer_node_free(ma_resource_manager* pReso
pDataBufferNode->data.encoded.pData = NULL; pDataBufferNode->data.encoded.pData = NULL;
pDataBufferNode->data.encoded.sizeInBytes = 0; pDataBufferNode->data.encoded.sizeInBytes = 0;
} else { } else {
if (pDataBufferNode->data.decoded.supplier == ma_decoded_data_supplier_buffer) { if (ma_resource_manager_data_buffer_node_get_decoded_data_supplier(pDataBufferNode) == ma_decoded_data_supplier_buffer) {
ma__free_from_callbacks((void*)pDataBufferNode->data.decoded.pData, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_DECODED_BUFFER*/); ma__free_from_callbacks((void*)pDataBufferNode->data.decoded.pData, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_DECODED_BUFFER*/);
pDataBufferNode->data.decoded.pData = NULL; pDataBufferNode->data.decoded.pData = NULL;
} else if (pDataBufferNode->data.decoded.supplier == ma_decoded_data_supplier_paged) { } else if (ma_resource_manager_data_buffer_node_get_decoded_data_supplier(pDataBufferNode) == ma_decoded_data_supplier_paged) {
ma_paged_audio_buffer_data_uninit(&pDataBufferNode->data.decoded.pagedData, &pResourceManager->config.allocationCallbacks); ma_paged_audio_buffer_data_uninit(&pDataBufferNode->data.decoded.pagedData, &pResourceManager->config.allocationCallbacks);
} else { } else {
/* Should never hit this. */ /* Should never hit this. */
...@@ -6518,12 +6528,12 @@ static ma_result ma_resource_manager_data_buffer_init_connector(ma_resource_mana ...@@ -6518,12 +6528,12 @@ static ma_result ma_resource_manager_data_buffer_init_connector(ma_resource_mana
*/ */
if (pDataBuffer->pNode->data.type == ma_resource_manager_data_buffer_encoding_decoded) { if (pDataBuffer->pNode->data.type == ma_resource_manager_data_buffer_encoding_decoded) {
/* If the source is of an unknown length we need to use a paged buffer. Otherwise we'll use a regular buffer which is a bit more efficient. */ /* If the source is of an unknown length we need to use a paged buffer. Otherwise we'll use a regular buffer which is a bit more efficient. */
if (pDataBuffer->pNode->data.decoded.supplier == ma_decoded_data_supplier_buffer) { if (ma_resource_manager_data_buffer_node_get_decoded_data_supplier(pDataBuffer->pNode) == ma_decoded_data_supplier_buffer) {
pDataBuffer->connectorType = ma_resource_manager_data_buffer_connector_buffer; pDataBuffer->connectorType = ma_resource_manager_data_buffer_connector_buffer;
} else if (pDataBuffer->pNode->data.decoded.supplier == ma_decoded_data_supplier_paged) { } else if (ma_resource_manager_data_buffer_node_get_decoded_data_supplier(pDataBuffer->pNode) == ma_decoded_data_supplier_paged) {
pDataBuffer->connectorType = ma_resource_manager_data_buffer_connector_paged_buffer; pDataBuffer->connectorType = ma_resource_manager_data_buffer_connector_paged_buffer;
} else { } else {
return MA_INVALID_ARGS; /* Unknown decoded data backend. */ return MA_INVALID_ARGS; /* Unknown decoded data supplier. */
} }
} else { } else {
pDataBuffer->connectorType = ma_resource_manager_data_buffer_connector_decoder; pDataBuffer->connectorType = ma_resource_manager_data_buffer_connector_decoder;
...@@ -6754,7 +6764,7 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager ...@@ -6754,7 +6764,7 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
/* TODO: This needs to be improved so that when loading asynchronously we post a message to the job queue instead of just waiting. */ /* TODO: This needs to be improved so that when loading asynchronously we post a message to the job queue instead of just waiting. */
if (pDataBuffer->pNode->data.type == ma_resource_manager_data_buffer_encoding_decoded) { if (pDataBuffer->pNode->data.type == ma_resource_manager_data_buffer_encoding_decoded) {
/* For the decoded case we need only wait for the data supplier to be initialized. */ /* For the decoded case we need only wait for the data supplier to be initialized. */
while (pDataBuffer->pNode->data.decoded.supplier == ma_decoded_data_supplier_unknown) { while (ma_resource_manager_data_buffer_node_get_decoded_data_supplier(pDataBuffer->pNode) == ma_decoded_data_supplier_unknown) {
ma_yield(); ma_yield();
} }
} else { } else {
...@@ -6989,12 +6999,12 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager ...@@ -6989,12 +6999,12 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
} }
if (result == MA_SUCCESS) { if (result == MA_SUCCESS) {
pDataBuffer->pNode->data.decoded.supplier = ma_decoded_data_supplier_buffer; ma_resource_manager_data_buffer_node_set_decoded_data_supplier(pDataBuffer->pNode, ma_decoded_data_supplier_buffer);
pDataBuffer->pNode->data.decoded.pData = pData; pDataBuffer->pNode->data.decoded.pData = pData;
pDataBuffer->pNode->data.decoded.frameCount = totalFrameCount; pDataBuffer->pNode->data.decoded.frameCount = totalFrameCount;
pDataBuffer->pNode->data.decoded.decodedFrameCount = totalFrameCount; /* We've decoded everything. */ pDataBuffer->pNode->data.decoded.decodedFrameCount = totalFrameCount; /* We've decoded everything. */
} else { } else {
pDataBuffer->pNode->data.decoded.supplier = ma_decoded_data_supplier_unknown; ma_resource_manager_data_buffer_node_set_decoded_data_supplier(pDataBuffer->pNode, ma_decoded_data_supplier_unknown);
pDataBuffer->pNode->data.decoded.pData = NULL; pDataBuffer->pNode->data.decoded.pData = NULL;
pDataBuffer->pNode->data.decoded.frameCount = 0; pDataBuffer->pNode->data.decoded.frameCount = 0;
pDataBuffer->pNode->data.decoded.decodedFrameCount = 0; pDataBuffer->pNode->data.decoded.decodedFrameCount = 0;
...@@ -7334,6 +7344,10 @@ MA_API ma_result ma_resource_manager_data_buffer_get_data_format(ma_resource_man ...@@ -7334,6 +7344,10 @@ MA_API ma_result ma_resource_manager_data_buffer_get_data_format(ma_resource_man
*pChannels = pDataBuffer->pNode->data.decoded.channels; *pChannels = pDataBuffer->pNode->data.decoded.channels;
*pSampleRate = pDataBuffer->pNode->data.decoded.sampleRate; *pSampleRate = pDataBuffer->pNode->data.decoded.sampleRate;
if (*pFormat == ma_format_unknown || *pChannels == 0) {
printf("format = %d; channels = %d; sampleRate = %d\n", *pFormat, *pChannels, *pSampleRate);
}
return MA_SUCCESS; return MA_SUCCESS;
} else { } else {
return ma_data_source_get_data_format(&pDataBuffer->connector.decoder, pFormat, pChannels, pSampleRate); return ma_data_source_get_data_format(&pDataBuffer->connector.decoder, pFormat, pChannels, pSampleRate);
...@@ -8682,7 +8696,7 @@ static ma_result ma_resource_manager_process_job__load_data_buffer(ma_resource_m ...@@ -8682,7 +8696,7 @@ static ma_result ma_resource_manager_process_job__load_data_buffer(ma_resource_m
framesRead = ma_decoder_read_pcm_frames(pDecoder, pData, pageSizeInFrames); framesRead = ma_decoder_read_pcm_frames(pDecoder, pData, pageSizeInFrames);
if (framesRead < pageSizeInFrames) { if (framesRead < pageSizeInFrames) {
/* We've read the entire sound. This is the simple case. We just need to set the result to MA_SUCCESS. */ /* We've read the entire sound. This is the simple case. We just need to set the result to MA_SUCCESS. */
pDataBuffer->pNode->data.decoded.supplier = ma_decoded_data_supplier_buffer; ma_resource_manager_data_buffer_node_set_decoded_data_supplier(pDataBuffer->pNode, ma_decoded_data_supplier_buffer);
pDataBuffer->pNode->data.decoded.pData = pData; pDataBuffer->pNode->data.decoded.pData = pData;
pDataBuffer->pNode->data.decoded.frameCount = framesRead; pDataBuffer->pNode->data.decoded.frameCount = framesRead;
...@@ -8743,7 +8757,7 @@ done: ...@@ -8743,7 +8757,7 @@ done:
/* The length is known. Use a simple buffer. */ /* The length is known. Use a simple buffer. */
pageDataBufferJob.pageDataBuffer.pInitNotification = NULL; /* <-- Clear this notification to NULL to ensure it's not signalled a second time at the end of decoding, which will be done for sounds of unknown length. */ pageDataBufferJob.pageDataBuffer.pInitNotification = NULL; /* <-- Clear this notification to NULL to ensure it's not signalled a second time at the end of decoding, which will be done for sounds of unknown length. */
pDataBuffer->pNode->data.decoded.supplier = ma_decoded_data_supplier_buffer; ma_resource_manager_data_buffer_node_set_decoded_data_supplier(pDataBuffer->pNode, ma_decoded_data_supplier_buffer);
pDataBuffer->pNode->data.decoded.pData = pData; pDataBuffer->pNode->data.decoded.pData = pData;
pDataBuffer->pNode->data.decoded.frameCount = totalFrameCount; pDataBuffer->pNode->data.decoded.frameCount = totalFrameCount;
...@@ -8759,7 +8773,7 @@ done: ...@@ -8759,7 +8773,7 @@ done:
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer, pJob->loadDataBuffer.pInitNotification); result = ma_resource_manager_data_buffer_init_connector(pDataBuffer, pJob->loadDataBuffer.pInitNotification);
} else { } else {
/* The length is unknown. Need to use a paged buffer. */ /* The length is unknown. Need to use a paged buffer. */
pDataBuffer->pNode->data.decoded.supplier = ma_decoded_data_supplier_paged; ma_resource_manager_data_buffer_node_set_decoded_data_supplier(pDataBuffer->pNode, ma_decoded_data_supplier_paged);
pDataBuffer->pNode->data.decoded.pData = NULL; /* <-- Not used for paged buffers. Set to NULL for safety. */ pDataBuffer->pNode->data.decoded.pData = NULL; /* <-- Not used for paged buffers. Set to NULL for safety. */
pDataBuffer->pNode->data.decoded.frameCount = 0; /* <-- Will be set at the end of decoding. */ pDataBuffer->pNode->data.decoded.frameCount = 0; /* <-- Will be set at the end of decoding. */
pDataBuffer->pNode->data.decoded.decodedFrameCount = framesRead; pDataBuffer->pNode->data.decoded.decodedFrameCount = framesRead;
......
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