mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 08:44:04 +02:00
Move ma_fence into the main library.
This commit is contained in:
+176
@@ -5815,6 +5815,38 @@ MA_API ma_result ma_event_signal(ma_event* pEvent);
|
|||||||
#endif /* MA_NO_THREADING */
|
#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
|
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;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************************************************************************************************
|
/************************************************************************************************************************************************************
|
||||||
*************************************************************************************************************************************************************
|
*************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
|||||||
@@ -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_API ma_result ma_async_notification_signal(ma_async_notification* pNotification)
|
||||||
{
|
{
|
||||||
ma_async_notification_callbacks* pNotificationCallbacks = (ma_async_notification_callbacks*)pNotification;
|
ma_async_notification_callbacks* pNotificationCallbacks = (ma_async_notification_callbacks*)pNotification;
|
||||||
|
|||||||
Reference in New Issue
Block a user