From 711854647a262d007d989d40565a3990fa7b8387 Mon Sep 17 00:00:00 2001 From: David Reid Date: Sat, 17 Jul 2021 16:32:27 +1000 Subject: [PATCH] Move ma_fence into the main library. --- miniaudio.h | 176 ++++++++++++++++++++++++++++++++++++ research/miniaudio_engine.h | 149 ------------------------------ 2 files changed, 176 insertions(+), 149 deletions(-) diff --git a/miniaudio.h b/miniaudio.h index c6da9824..2b8ba063 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -5815,6 +5815,38 @@ MA_API ma_result ma_event_signal(ma_event* pEvent); #endif /* MA_NO_THREADING */ +/* +Fence +===== +This locks while the counter is larger than 0. Counter can be incremented and decremented by any +thread, but care needs to be taken when waiting. It is possible for one thread to acquire the +fence just as another thread returns from ma_fence_wait(). + +The idea behind a fence is to allow you to wait for a group of operations to complete. When an +operation starts, the counter is incremented which locks the fence. When the operation completes, +the fence will be released which decrements the counter. ma_fence_wait() will block until the +counter hits zero. + +If threading is disabled, ma_fence_wait() will spin on the counter. +*/ +typedef struct +{ +#ifndef MA_NO_THREADING + ma_event e; +#endif + ma_uint32 counter; +} ma_fence; + +MA_API ma_result ma_fence_init(ma_fence* pFence); +MA_API void ma_fence_uninit(ma_fence* pFence); +MA_API ma_result ma_fence_acquire(ma_fence* pFence); /* Increment counter. */ +MA_API ma_result ma_fence_release(ma_fence* pFence); /* Decrement counter. */ +MA_API ma_result ma_fence_wait(ma_fence* pFence); /* Wait for counter to reach 0. */ + + + + + /************************************************************************************************************************************************************ Utiltities @@ -11365,6 +11397,150 @@ MA_API ma_result ma_semaphore_release(ma_semaphore* pSemaphore) +#define MA_FENCE_COUNTER_MAX 0x7FFFFFFF + +MA_API ma_result ma_fence_init(ma_fence* pFence) +{ + if (pFence == NULL) { + return MA_INVALID_ARGS; + } + + MA_ZERO_OBJECT(pFence); + pFence->counter = 0; + + #ifndef MA_NO_THREADING + { + ma_result result; + + result = ma_event_init(&pFence->e); + if (result != MA_SUCCESS) { + return result; + } + } + #endif + + return MA_SUCCESS; +} + +MA_API void ma_fence_uninit(ma_fence* pFence) +{ + if (pFence == NULL) { + return; + } + + #ifndef MA_NO_THREADING + { + ma_event_uninit(&pFence->e); + } + #endif + + MA_ZERO_OBJECT(pFence); +} + +MA_API ma_result ma_fence_acquire(ma_fence* pFence) +{ + if (pFence == NULL) { + return MA_INVALID_ARGS; + } + + for (;;) { + ma_uint32 oldCounter = c89atomic_load_32(&pFence->counter); + ma_uint32 newCounter = oldCounter + 1; + + /* Make sure we're not about to exceed our maximum value. */ + if (newCounter > MA_FENCE_COUNTER_MAX) { + MA_ASSERT(MA_FALSE); + return MA_OUT_OF_RANGE; + } + + if (c89atomic_compare_exchange_weak_32(&pFence->counter, &oldCounter, newCounter)) { + return MA_SUCCESS; + } else { + if (oldCounter == MA_FENCE_COUNTER_MAX) { + MA_ASSERT(MA_FALSE); + return MA_OUT_OF_RANGE; /* The other thread took the last available slot. Abort. */ + } + } + } + + /* Should never get here. */ + /*return MA_SUCCESS;*/ +} + +MA_API ma_result ma_fence_release(ma_fence* pFence) +{ + if (pFence == NULL) { + return MA_INVALID_ARGS; + } + + for (;;) { + ma_uint32 oldCounter = c89atomic_load_32(&pFence->counter); + ma_uint32 newCounter = oldCounter - 1; + + if (oldCounter == 0) { + MA_ASSERT(MA_FALSE); + return MA_INVALID_OPERATION; /* Acquire/release mismatch. */ + } + + if (c89atomic_compare_exchange_weak_32(&pFence->counter, &oldCounter, newCounter)) { + #ifndef MA_NO_THREADING + { + if (newCounter == 0) { + ma_event_signal(&pFence->e); /* <-- ma_fence_wait() will be waiting on this. */ + } + } + #endif + + return MA_SUCCESS; + } else { + if (oldCounter == 0) { + MA_ASSERT(MA_FALSE); + return MA_INVALID_OPERATION; /* Another thread has taken the 0 slot. Acquire/release mismatch. */ + } + } + } + + /* Should never get here. */ + /*return MA_SUCCESS;*/ +} + +MA_API ma_result ma_fence_wait(ma_fence* pFence) +{ + if (pFence == NULL) { + return MA_INVALID_ARGS; + } + + for (;;) { + ma_uint32 counter; + + counter = c89atomic_load_32(&pFence->counter); + if (counter == 0) { + /* + Counter has hit zero. By the time we get here some other thread may have acquired the + fence again, but that is where the caller needs to take care with how they se the fence. + */ + return MA_SUCCESS; + } + + /* Getting here means the counter is > 0. We'll need to wait for something to happen. */ + #ifndef MA_NO_THREADING + { + ma_result result; + + result = ma_event_wait(&pFence->e); + if (result != MA_SUCCESS) { + return result; + } + } + #endif + } + + /* Should never get here. */ + /*return MA_INVALID_OPERATION;*/ +} + + + /************************************************************************************************************************************************************ ************************************************************************************************************************************************************* diff --git a/research/miniaudio_engine.h b/research/miniaudio_engine.h index 3fcc1f20..a25b1d8d 100644 --- a/research/miniaudio_engine.h +++ b/research/miniaudio_engine.h @@ -1148,29 +1148,7 @@ MA_API ma_result ma_slot_allocator_free(ma_slot_allocator* pAllocator, ma_uint64 -/* -Fence -===== -This locks while the counter is larger than 0. Counter can be incremented and decremented by any -thread, but care needs to be taken when waiting. It is possible for one thread to acquire the -fence just as another thread returns from ma_fence_wait(). -The idea behind a fence is to allow you to wait for a group of operations to complete. When an -operation starts, the counter is incremented which locks the fence. When the operation completes, -the fence will be released which decrements the counter. ma_fence_wait() will block until the -counter hits zero. -*/ -typedef struct -{ - ma_event e; - ma_uint32 counter; -} ma_fence; - -MA_API ma_result ma_fence_init(ma_fence* pFence); -MA_API void ma_fence_uninit(ma_fence* pFence); -MA_API ma_result ma_fence_acquire(ma_fence* pFence); /* Increment counter. */ -MA_API ma_result ma_fence_release(ma_fence* pFence); /* Decrement counter. */ -MA_API ma_result ma_fence_wait(ma_fence* pFence); /* Wait for counter to reach 0. */ @@ -5123,133 +5101,6 @@ MA_API ma_result ma_slot_allocator_free(ma_slot_allocator* pAllocator, ma_uint64 -#define MA_FENCE_COUNTER_MAX 0x7FFFFFFF - -MA_API ma_result ma_fence_init(ma_fence* pFence) -{ - ma_result result; - - if (pFence == NULL) { - return MA_INVALID_ARGS; - } - - MA_ZERO_OBJECT(pFence); - pFence->counter = 0; - - result = ma_event_init(&pFence->e); - if (result != MA_SUCCESS) { - return result; - } - - return MA_SUCCESS; -} - -MA_API void ma_fence_uninit(ma_fence* pFence) -{ - if (pFence == NULL) { - return; - } - - ma_event_uninit(&pFence->e); - - MA_ZERO_OBJECT(pFence); -} - -MA_API ma_result ma_fence_acquire(ma_fence* pFence) -{ - if (pFence == NULL) { - return MA_INVALID_ARGS; - } - - for (;;) { - ma_uint32 oldCounter = c89atomic_load_32(&pFence->counter); - ma_uint32 newCounter = oldCounter + 1; - - /* Make sure we're not about to exceed our maximum value. */ - if (newCounter > MA_FENCE_COUNTER_MAX) { - MA_ASSERT(MA_FALSE); - return MA_OUT_OF_RANGE; - } - - if (c89atomic_compare_exchange_weak_32(&pFence->counter, &oldCounter, newCounter)) { - return MA_SUCCESS; - } else { - if (oldCounter == MA_FENCE_COUNTER_MAX) { - MA_ASSERT(MA_FALSE); - return MA_OUT_OF_RANGE; /* The other thread took the last available slot. Abort. */ - } - } - } - - /* Should never get here. */ - /*return MA_SUCCESS;*/ -} - -MA_API ma_result ma_fence_release(ma_fence* pFence) -{ - if (pFence == NULL) { - return MA_INVALID_ARGS; - } - - for (;;) { - ma_uint32 oldCounter = c89atomic_load_32(&pFence->counter); - ma_uint32 newCounter = oldCounter - 1; - - if (oldCounter == 0) { - MA_ASSERT(MA_FALSE); - return MA_INVALID_OPERATION; /* Acquire/release mismatch. */ - } - - if (c89atomic_compare_exchange_weak_32(&pFence->counter, &oldCounter, newCounter)) { - if (newCounter == 0) { - ma_event_signal(&pFence->e); /* <-- ma_fence_wait() will be waiting on this. */ - } - - return MA_SUCCESS; - } else { - if (oldCounter == 0) { - MA_ASSERT(MA_FALSE); - return MA_INVALID_OPERATION; /* Another thread has taken the 0 slot. Acquire/release mismatch. */ - } - } - } - - /* Should never get here. */ - /*return MA_SUCCESS;*/ -} - -MA_API ma_result ma_fence_wait(ma_fence* pFence) -{ - if (pFence == NULL) { - return MA_INVALID_ARGS; - } - - for (;;) { - ma_result result; - ma_uint32 counter; - - counter = c89atomic_load_32(&pFence->counter); - if (counter == 0) { - /* - Counter has hit zero. By the time we get here some other thread may have acquired the - fence again, but that is where the caller needs to take care with how they se the fence. - */ - return MA_SUCCESS; - } - - /* Getting here means the counter is > 0. We'll need to wait for something to happen. */ - result = ma_event_wait(&pFence->e); - if (result != MA_SUCCESS) { - return result; - } - } - - /* Should never get here. */ - /*return MA_INVALID_OPERATION;*/ -} - - - MA_API ma_result ma_async_notification_signal(ma_async_notification* pNotification) { ma_async_notification_callbacks* pNotificationCallbacks = (ma_async_notification_callbacks*)pNotification;