[*] Updated bit utilities
[*] Updated default string type [*] Spinlocks can now timeout [*] Finish RW lock write entrant mode
This commit is contained in:
parent
fac6571504
commit
749b8deb8d
@ -359,8 +359,8 @@ namespace Aurora::Memory
|
||||
|
||||
// String API
|
||||
|
||||
inline bool WriteString(const AuString &string, EStringType type, Locale::ECodePage codepage = Locale::ECodePage::eUTF8);
|
||||
inline bool ReadString(AuString &string, EStringType type, Locale::ECodePage codepage = Locale::ECodePage::eUTF8);
|
||||
inline bool WriteString(const AuString &string, EStringType type = EStringType::eStringDword, Locale::ECodePage codepage = Locale::ECodePage::eUTF8);
|
||||
inline bool ReadString(AuString &string, EStringType type = EStringType::eStringDword, Locale::ECodePage codepage = Locale::ECodePage::eUTF8);
|
||||
|
||||
// Copy, concat, etc
|
||||
inline bool WriteFrom(ByteBuffer &buffer, AuUInt length);
|
||||
|
@ -26,11 +26,7 @@ namespace Aurora::Threading::Primitives
|
||||
void Unlock() override;
|
||||
|
||||
private:
|
||||
#if defined(_AU_HAS_ATOMIC_INTRINS)
|
||||
volatile AuAtomicInt value_;
|
||||
#else
|
||||
std::atomic_long value_;
|
||||
#endif
|
||||
AuAtomicInt value_;
|
||||
};
|
||||
|
||||
AUKN_SHARED_API(SpinLock, SpinLock);
|
||||
|
@ -10,9 +10,30 @@
|
||||
template<typename T>
|
||||
struct AuAtomicUtils
|
||||
{
|
||||
/**
|
||||
* @brief Sets bit offset in in
|
||||
* @return original value
|
||||
*/
|
||||
static T Set(T *in, AuUInt8 offset);
|
||||
|
||||
/**
|
||||
* @brief Adds addend to in
|
||||
* @return updated value
|
||||
*/
|
||||
static T Add(T *in, T addend);
|
||||
|
||||
/**
|
||||
* @brief Subtracts the minuend from in
|
||||
* @return updated value
|
||||
*/
|
||||
static T Sub(T *in, T minuend);
|
||||
|
||||
/**
|
||||
* @brief Generic bitwise compare exchange
|
||||
* @param replace replacement value for in if in matches compare
|
||||
* @param compare required reference value
|
||||
* @return original value
|
||||
*/
|
||||
static T CompareExchange(T *in, T replace, T compare);
|
||||
};
|
||||
|
||||
@ -129,6 +150,36 @@ inline auline AuUInt16 AuAtomicUtils<AuUInt16>::Set(AuUInt16 *in, AuUInt8 offset
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline auline AuInt64 AuAtomicUtils<AuInt64>::Set(AuInt64 *in, AuUInt8 offset)
|
||||
{
|
||||
return _InterlockedOr64(reinterpret_cast<long long volatile *>(in), AuUInt64(1) << offset);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline auline AuInt32 AuAtomicUtils<AuInt32>::Set(AuInt32 *in, AuUInt8 offset)
|
||||
{
|
||||
return _InterlockedOr(reinterpret_cast<long volatile *>(in), 1 << offset);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline auline long AuAtomicUtils<long>::Set(long *in, AuUInt8 offset)
|
||||
{
|
||||
return _InterlockedOr(reinterpret_cast<long volatile *>(in), 1 << offset);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline auline unsigned long AuAtomicUtils<unsigned long>::Set(unsigned long *in, AuUInt8 offset)
|
||||
{
|
||||
return _InterlockedOr(reinterpret_cast<long volatile *>(in), 1 << offset);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline auline AuInt16 AuAtomicUtils<AuInt16>::Set(AuInt16 *in, AuUInt8 offset)
|
||||
{
|
||||
return _InterlockedOr16(reinterpret_cast<short volatile *>(in), 1 << offset);
|
||||
}
|
||||
|
||||
#elif defined(AURORA_COMPILER_CLANG) || defined(AURORA_COMPILER_GCC)
|
||||
|
||||
template<typename T>
|
||||
@ -152,7 +203,7 @@ inline auline T AuAtomicUtils<T>::Sub(T *in, T minuend)
|
||||
template<typename T>
|
||||
inline auline T AuAtomicUtils<T>::Set(T *in, AuUInt8 offset)
|
||||
{
|
||||
return __sync_or_and_fetch(in, T(1) << offset);
|
||||
return __sync_fetch_and_or(in, T(1) << offset);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -53,6 +53,12 @@ inline AuUInt32 AuEndianUtils<AuUInt32>::Swap(AuUInt32 in)
|
||||
return _byteswap_ulong(in);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline unsigned long AuEndianUtils<unsigned long>::Swap(unsigned long in)
|
||||
{
|
||||
return _byteswap_ulong(in);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline AuUInt16 AuEndianUtils<AuUInt16>::Swap(AuUInt16 in)
|
||||
{
|
||||
|
@ -127,13 +127,12 @@ namespace Aurora::Threading::Primitives
|
||||
|
||||
bool RWLockImpl::TryLockRead()
|
||||
{
|
||||
AU_LOCK_GUARD(mutex_);
|
||||
|
||||
if (this->state_ == -1)
|
||||
{
|
||||
return this->reentrantWriteLockHandle_ == AuThreads::GetThreadId();
|
||||
}
|
||||
|
||||
AU_LOCK_GUARD(mutex_);
|
||||
this->state_++;
|
||||
return true;
|
||||
}
|
||||
@ -147,6 +146,7 @@ namespace Aurora::Threading::Primitives
|
||||
return false;
|
||||
}
|
||||
|
||||
this->reentrantWriteLockHandle_ = AuThreads::GetThreadId();
|
||||
this->state_ = -1;
|
||||
return true;
|
||||
}
|
||||
|
@ -48,17 +48,21 @@ namespace Aurora::Threading::Primitives
|
||||
AcquireSRWLockShared(&lock_); // we use atomics. using shared is fine, let's not get congested early
|
||||
while (!TryLock())
|
||||
{
|
||||
start = AuTime::CurrentInternalClockMS();
|
||||
AuUInt32 timeoutMs = INFINITE;
|
||||
|
||||
if (end <= start)
|
||||
if (timeout != 0)
|
||||
{
|
||||
ReleaseSRWLockShared(&lock_);
|
||||
return false;
|
||||
start = Time::CurrentClockMS();
|
||||
if (start >= end)
|
||||
{
|
||||
ReleaseSRWLockShared(&lock_);
|
||||
return false;
|
||||
}
|
||||
|
||||
timeoutMs = end - start;
|
||||
}
|
||||
|
||||
auto timeout = end - start;
|
||||
|
||||
if (!::SleepConditionVariableSRW(&winCond_, &lock_, AuUInt32(timeout), CONDITION_VARIABLE_LOCKMODE_SHARED))
|
||||
if (!::SleepConditionVariableSRW(&winCond_, &lock_, AuUInt32(timeoutMs), CONDITION_VARIABLE_LOCKMODE_SHARED))
|
||||
{
|
||||
ReleaseSRWLockShared(&lock_);
|
||||
return false;
|
||||
|
@ -54,16 +54,33 @@ namespace Aurora::Threading::Primitives
|
||||
|
||||
bool SpinLock::Lock(AuUInt64 timeout)
|
||||
{
|
||||
#if defined(_AU_HAS_ATOMIC_INTRINS)
|
||||
while (_interlockedbittestandset(&value_, 0))
|
||||
#else
|
||||
while (value_.fetch_or(1))
|
||||
#endif
|
||||
if (timeout == 0)
|
||||
{
|
||||
long count = 0;
|
||||
while (value_)
|
||||
while (AuAtomicSet(&this->value_, 0))
|
||||
{
|
||||
YieldCpu(count);
|
||||
long count = 0;
|
||||
while (value_)
|
||||
{
|
||||
YieldCpu(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AuUInt64 startTime = AuTime::CurrentInternalClockMS();
|
||||
AuUInt64 endTime = startTime + timeout;
|
||||
|
||||
while (AuAtomicSet(&this->value_, 0))
|
||||
{
|
||||
long count = 0;
|
||||
while (value_)
|
||||
{
|
||||
if (endTime <= AuTime::CurrentInternalClockMS())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
YieldCpu(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user