From 4f8e8de301ce86f7f39d9a7d8ca19018fb729fd1 Mon Sep 17 00:00:00 2001 From: David Reid Date: Mon, 14 Nov 2022 16:43:16 +1000 Subject: [PATCH] Migrate atomics from ma_device to new atomics system. --- miniaudio.h | 59 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/miniaudio.h b/miniaudio.h index 62f67075..cf74b856 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -4256,7 +4256,6 @@ MA_ATOMIC_SAFE_TYPE_DECL(f32, 4, float) MA_ATOMIC_SAFE_TYPE_DECL(32, 4, bool32) - /* Spinlocks are 32-bit for compatibility reasons. */ typedef ma_uint32 ma_spinlock; @@ -6308,6 +6307,9 @@ typedef enum ma_device_state_stopping = 4 /* Transitioning from a started state to stopped. */ } ma_device_state; +MA_ATOMIC_SAFE_TYPE_DECL(i32, 4, device_state) + + #ifdef MA_SUPPORT_WASAPI /* We need a IMMNotificationClient object for WASAPI. */ typedef struct @@ -7372,7 +7374,7 @@ struct ma_device ma_context* pContext; ma_device_type type; ma_uint32 sampleRate; - MA_ATOMIC(4, ma_device_state) state; /* The state of the device is variable and can change at any time on any thread. Must be used atomically. */ + ma_atomic_device_state state; /* The state of the device is variable and can change at any time on any thread. Must be used atomically. */ ma_device_data_proc onData; /* Set once at initialization time and should not be changed after. */ ma_device_notification_proc onNotification; /* Set once at initialization time and should not be changed after. */ ma_stop_proc onStop; /* DEPRECATED. Use the notification callback instead. Set once at initialization time and should not be changed after. */ @@ -7388,7 +7390,7 @@ struct ma_device ma_bool8 noClip; ma_bool8 noDisableDenormals; ma_bool8 noFixedSizedCallback; - MA_ATOMIC(4, float) masterVolumeFactor; /* Linear 0..1. Can be read and written simultaneously by different threads. Must be used atomically. */ + ma_atomic_float masterVolumeFactor; /* Linear 0..1. Can be read and written simultaneously by different threads. Must be used atomically. */ ma_duplex_rb duplexRB; /* Intermediary buffer for duplex device on asynchronous backends. */ struct { @@ -7476,8 +7478,8 @@ struct ma_device void* pMappedBufferPlayback; ma_uint32 mappedBufferPlaybackCap; ma_uint32 mappedBufferPlaybackLen; - MA_ATOMIC(4, ma_bool32) isStartedCapture; /* Can be read and written simultaneously across different threads. Must be used atomically, and must be 32-bit. */ - MA_ATOMIC(4, ma_bool32) isStartedPlayback; /* Can be read and written simultaneously across different threads. Must be used atomically, and must be 32-bit. */ + ma_atomic_bool32 isStartedCapture; /* Can be read and written simultaneously across different threads. Must be used atomically, and must be 32-bit. */ + ma_atomic_bool32 isStartedPlayback; /* Can be read and written simultaneously across different threads. Must be used atomically, and must be 32-bit. */ ma_uint32 loopbackProcessID; ma_bool8 loopbackProcessExclude; ma_bool8 noAutoConvertSRC; /* When set to true, disables the use of AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM. */ @@ -7650,7 +7652,7 @@ struct ma_device ma_uint32 currentPeriodFramesRemainingCapture; ma_uint64 lastProcessedFramePlayback; ma_uint64 lastProcessedFrameCapture; - MA_ATOMIC(4, ma_bool32) isStarted; /* Read and written by multiple threads. Must be used atomically, and must be 32-bit for compiler compatibility. */ + ma_atomic_bool32 isStarted; /* Read and written by multiple threads. Must be used atomically, and must be 32-bit for compiler compatibility. */ } null_device; #endif }; @@ -15580,7 +15582,7 @@ MA_ATOMIC_SAFE_TYPE_IMPL(i32, int32) MA_ATOMIC_SAFE_TYPE_IMPL(64, uint64) MA_ATOMIC_SAFE_TYPE_IMPL(f32, float) MA_ATOMIC_SAFE_TYPE_IMPL(32, bool32) - +MA_ATOMIC_SAFE_TYPE_IMPL(i32, device_state) MA_API ma_uint64 ma_calculate_frame_count_after_resampling(ma_uint32 sampleRateOut, ma_uint32 sampleRateIn, ma_uint64 frameCountIn) @@ -18606,7 +18608,7 @@ static ma_result ma_device__handle_duplex_callback_playback(ma_device* pDevice, /* A helper for changing the state of the device. */ static MA_INLINE void ma_device__set_state(ma_device* pDevice, ma_device_state newState) { - c89atomic_exchange_i32((ma_int32*)&pDevice->state, (ma_int32)newState); + ma_atomic_device_state_set(&pDevice->state, newState); } @@ -19117,7 +19119,7 @@ static ma_result ma_device_start__null(ma_device* pDevice) ma_device_do_operation__null(pDevice, MA_DEVICE_OP_START__NULL); - c89atomic_exchange_32(&pDevice->null_device.isStarted, MA_TRUE); + ma_atomic_bool32_set(&pDevice->null_device.isStarted, MA_TRUE); return MA_SUCCESS; } @@ -19127,10 +19129,17 @@ static ma_result ma_device_stop__null(ma_device* pDevice) ma_device_do_operation__null(pDevice, MA_DEVICE_OP_SUSPEND__NULL); - c89atomic_exchange_32(&pDevice->null_device.isStarted, MA_FALSE); + ma_atomic_bool32_set(&pDevice->null_device.isStarted, MA_FALSE); return MA_SUCCESS; } +static ma_bool32 ma_device_is_started__null(ma_device* pDevice) +{ + MA_ASSERT(pDevice != NULL); + + return ma_atomic_bool32_get(&pDevice->null_device.isStarted); +} + static ma_result ma_device_write__null(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten) { ma_result result = MA_SUCCESS; @@ -19141,7 +19150,7 @@ static ma_result ma_device_write__null(ma_device* pDevice, const void* pPCMFrame *pFramesWritten = 0; } - wasStartedOnEntry = c89atomic_load_32(&pDevice->null_device.isStarted); + wasStartedOnEntry = ma_device_is_started__null(pDevice); /* Keep going until everything has been read. */ totalPCMFramesProcessed = 0; @@ -19167,7 +19176,7 @@ static ma_result ma_device_write__null(ma_device* pDevice, const void* pPCMFrame if (pDevice->null_device.currentPeriodFramesRemainingPlayback == 0) { pDevice->null_device.currentPeriodFramesRemainingPlayback = 0; - if (!c89atomic_load_32(&pDevice->null_device.isStarted) && !wasStartedOnEntry) { + if (!ma_device_is_started__null(pDevice) && !wasStartedOnEntry) { result = ma_device_start__null(pDevice); if (result != MA_SUCCESS) { break; @@ -19187,7 +19196,7 @@ static ma_result ma_device_write__null(ma_device* pDevice, const void* pPCMFrame ma_uint64 currentFrame; /* Stop waiting if the device has been stopped. */ - if (!c89atomic_load_32(&pDevice->null_device.isStarted)) { + if (!ma_device_is_started__null(pDevice)) { break; } @@ -19258,7 +19267,7 @@ static ma_result ma_device_read__null(ma_device* pDevice, void* pPCMFrames, ma_u ma_uint64 currentFrame; /* Stop waiting if the device has been stopped. */ - if (!c89atomic_load_32(&pDevice->null_device.isStarted)) { + if (!ma_device_is_started__null(pDevice)) { break; } @@ -22229,8 +22238,8 @@ static ma_result ma_device_init__wasapi(ma_device* pDevice, const ma_device_conf } #endif - c89atomic_exchange_32(&pDevice->wasapi.isStartedCapture, MA_FALSE); - c89atomic_exchange_32(&pDevice->wasapi.isStartedPlayback, MA_FALSE); + ma_atomic_bool32_set(&pDevice->wasapi.isStartedCapture, MA_FALSE); + ma_atomic_bool32_set(&pDevice->wasapi.isStartedPlayback, MA_FALSE); return MA_SUCCESS; } @@ -22335,7 +22344,7 @@ static ma_result ma_device_start__wasapi(ma_device* pDevice) return ma_result_from_HRESULT(hr); } - c89atomic_exchange_32(&pDevice->wasapi.isStartedCapture, MA_TRUE); + ma_atomic_bool32_set(&pDevice->wasapi.isStartedCapture, MA_TRUE); } if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) { @@ -22345,7 +22354,7 @@ static ma_result ma_device_start__wasapi(ma_device* pDevice) return ma_result_from_HRESULT(hr); } - c89atomic_exchange_32(&pDevice->wasapi.isStartedPlayback, MA_TRUE); + ma_atomic_bool32_set(&pDevice->wasapi.isStartedPlayback, MA_TRUE); } return MA_SUCCESS; @@ -22385,7 +22394,7 @@ static ma_result ma_device_stop__wasapi(ma_device* pDevice) pDevice->wasapi.mappedBufferCaptureLen = 0; } - c89atomic_exchange_32(&pDevice->wasapi.isStartedCapture, MA_FALSE); + ma_atomic_bool32_set(&pDevice->wasapi.isStartedCapture, MA_FALSE); } if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) { @@ -22393,7 +22402,7 @@ static ma_result ma_device_stop__wasapi(ma_device* pDevice) The buffer needs to be drained before stopping the device. Not doing this will result in the last few frames not getting output to the speakers. This is a problem for very short sounds because it'll result in a significant portion of it not getting played. */ - if (c89atomic_load_32(&pDevice->wasapi.isStartedPlayback)) { + if (ma_atomic_bool32_get(&pDevice->wasapi.isStartedPlayback)) { /* We need to make sure we put a timeout here or else we'll risk getting stuck in a deadlock in some cases. */ DWORD waitTime = pDevice->wasapi.actualBufferSizeInFramesPlayback / pDevice->playback.internalSampleRate; @@ -22447,7 +22456,7 @@ static ma_result ma_device_stop__wasapi(ma_device* pDevice) pDevice->wasapi.mappedBufferPlaybackLen = 0; } - c89atomic_exchange_32(&pDevice->wasapi.isStartedPlayback, MA_FALSE); + ma_atomic_bool32_set(&pDevice->wasapi.isStartedPlayback, MA_FALSE); } return MA_SUCCESS; @@ -40571,7 +40580,7 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC pDevice->noClip = pConfig->noClip; pDevice->noDisableDenormals = pConfig->noDisableDenormals; pDevice->noFixedSizedCallback = pConfig->noFixedSizedCallback; - pDevice->masterVolumeFactor = 1; + ma_atomic_float_set(&pDevice->masterVolumeFactor, 1); pDevice->type = pConfig->deviceType; pDevice->sampleRate = pConfig->sampleRate; @@ -41279,7 +41288,7 @@ MA_API ma_device_state ma_device_get_state(const ma_device* pDevice) return ma_device_state_uninitialized; } - return (ma_device_state)c89atomic_load_i32((ma_int32*)&pDevice->state); /* Naughty cast to get rid of a const warning. */ + return ma_atomic_device_state_get((ma_atomic_device_state*)&pDevice->state); /* Naughty cast to get rid of a const warning. */ } MA_API ma_result ma_device_set_master_volume(ma_device* pDevice, float volume) @@ -41292,7 +41301,7 @@ MA_API ma_result ma_device_set_master_volume(ma_device* pDevice, float volume) return MA_INVALID_ARGS; } - c89atomic_exchange_f32(&pDevice->masterVolumeFactor, volume); + ma_atomic_float_set(&pDevice->masterVolumeFactor, volume); return MA_SUCCESS; } @@ -41308,7 +41317,7 @@ MA_API ma_result ma_device_get_master_volume(ma_device* pDevice, float* pVolume) return MA_INVALID_ARGS; } - *pVolume = c89atomic_load_f32(&pDevice->masterVolumeFactor); + *pVolume = ma_atomic_float_get(&pDevice->masterVolumeFactor); return MA_SUCCESS; }