ios-unity/Libraries/external/baselib/Include/C/Internal/Baselib_Lock_FutexBased.inl.h
2023-02-10 15:13:26 +08:00

93 lines
3.0 KiB
C

#pragma once
#include "../Baselib_CountdownTimer.h"
#include "../Baselib_Atomic_TypeSafe.h"
#include "../Baselib_SystemFutex.h"
enum Detail_Baselib_Lock_State
{
Detail_Baselib_Lock_UNLOCKED = 0,
Detail_Baselib_Lock_LOCKED = 1,
Detail_Baselib_Lock_CONTENDED = 2,
};
typedef struct Baselib_Lock
{
int32_t state;
char _cachelineSpacer[PLATFORM_CACHE_LINE_SIZE - sizeof(int32_t)];
} Baselib_Lock;
BASELIB_INLINE_API Baselib_Lock Baselib_Lock_Create(void)
{
Baselib_Lock lock = {Detail_Baselib_Lock_UNLOCKED, {0}};
return lock;
}
COMPILER_WARN_UNUSED_RESULT
BASELIB_INLINE_API bool Baselib_Lock_TryAcquire(Baselib_Lock* lock)
{
int32_t previousState = Detail_Baselib_Lock_UNLOCKED;
do
{
if (Baselib_atomic_compare_exchange_weak_32_acquire_relaxed(&lock->state, &previousState, Detail_Baselib_Lock_LOCKED))
return true;
}
while (previousState == Detail_Baselib_Lock_UNLOCKED);
return false;
}
BASELIB_INLINE_API void Baselib_Lock_Acquire(Baselib_Lock* lock)
{
int32_t previousState = Detail_Baselib_Lock_UNLOCKED;
do
{
if (Baselib_atomic_compare_exchange_weak_32_acquire_relaxed(&lock->state, &previousState, previousState + 1))
break;
}
while (previousState != Detail_Baselib_Lock_CONTENDED);
while (OPTIMIZER_LIKELY(previousState != Detail_Baselib_Lock_UNLOCKED))
{
Baselib_SystemFutex_Wait(&lock->state, Detail_Baselib_Lock_CONTENDED, UINT32_MAX);
previousState = Baselib_atomic_exchange_32_relaxed(&lock->state, Detail_Baselib_Lock_CONTENDED);
}
}
COMPILER_WARN_UNUSED_RESULT
BASELIB_INLINE_API bool Baselib_Lock_TryTimedAcquire(Baselib_Lock* lock, const uint32_t timeoutInMilliseconds)
{
int32_t previousState = Detail_Baselib_Lock_UNLOCKED;
do
{
if (Baselib_atomic_compare_exchange_weak_32_acquire_relaxed(&lock->state, &previousState, previousState + 1))
break;
}
while (previousState != Detail_Baselib_Lock_CONTENDED);
if (OPTIMIZER_LIKELY(previousState == Detail_Baselib_Lock_UNLOCKED))
return true;
uint32_t timeLeft = timeoutInMilliseconds;
const Baselib_CountdownTimer timer = Baselib_CountdownTimer_StartMs(timeoutInMilliseconds);
do
{
Baselib_SystemFutex_Wait(&lock->state, Detail_Baselib_Lock_CONTENDED, timeoutInMilliseconds);
const int32_t previousState = Baselib_atomic_exchange_32_relaxed(&lock->state, Detail_Baselib_Lock_CONTENDED);
if (previousState == Detail_Baselib_Lock_UNLOCKED)
return true;
timeLeft = Baselib_CountdownTimer_GetTimeLeftInMilliseconds(timer);
}
while (timeLeft);
return false;
}
BASELIB_INLINE_API void Baselib_Lock_Release(Baselib_Lock* lock)
{
const int32_t previousState = Baselib_atomic_exchange_32_release(&lock->state, Detail_Baselib_Lock_UNLOCKED);
if (previousState == Detail_Baselib_Lock_CONTENDED)
Baselib_SystemFutex_Notify(&lock->state, 1, Baselib_WakeupFallbackStrategy_OneByOne);
}
BASELIB_INLINE_API void Baselib_Lock_Free(Baselib_Lock* lock)
{
}