[*] Fix abnormal ::UnlockWrite performance under heavyweight native WaitOnAddress platforms (Linux, BSD-like, etc)
This commit is contained in:
parent
5d12f1a203
commit
7357764cfc
@ -150,15 +150,25 @@ namespace Aurora::Threading::Primitives
|
|||||||
return (AuUInt32 *)this->conditionVariableWriter_;
|
return (AuUInt32 *)this->conditionVariableWriter_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<bool bIsWriteRecursionAllowed>
|
||||||
|
AuUInt32 *RWLockImpl<bIsWriteRecursionAllowed>::GetReadSleepCounter()
|
||||||
|
{
|
||||||
|
return (AuUInt32 *)this->conditionVariable_;
|
||||||
|
}
|
||||||
|
|
||||||
template<bool bIsWriteRecursionAllowed>
|
template<bool bIsWriteRecursionAllowed>
|
||||||
bool RWLockImpl<bIsWriteRecursionAllowed>::LockReadNSAbs(AuUInt64 uTimeout)
|
bool RWLockImpl<bIsWriteRecursionAllowed>::LockReadNSAbs(AuUInt64 uTimeout)
|
||||||
{
|
{
|
||||||
|
AuInt32 iCurState {};
|
||||||
|
bool bRet {};
|
||||||
|
|
||||||
if (this->TryLockRead())
|
if (this->TryLockRead())
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
AuInt32 iCurState {};
|
auto pCounter = this->GetReadSleepCounter();
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
iCurState = this->state_;
|
iCurState = this->state_;
|
||||||
@ -167,7 +177,11 @@ namespace Aurora::Threading::Primitives
|
|||||||
{
|
{
|
||||||
if (gUseFutexRWLock)
|
if (gUseFutexRWLock)
|
||||||
{
|
{
|
||||||
if (!InternalLTSWaitOnAddressHighRes((const void *)&this->state_, &iCurState, sizeof(iCurState), uTimeout))
|
AuAtomicAdd(pCounter, 1u);
|
||||||
|
bRet = InternalLTSWaitOnAddressHighRes((const void *)&this->state_, &iCurState, sizeof(iCurState), uTimeout);
|
||||||
|
AuAtomicSub(pCounter, 1u);
|
||||||
|
|
||||||
|
if (!bRet)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -212,6 +226,9 @@ namespace Aurora::Threading::Primitives
|
|||||||
template<bool bIsWriteRecursionAllowed>
|
template<bool bIsWriteRecursionAllowed>
|
||||||
bool RWLockImpl<bIsWriteRecursionAllowed>::LockReadNS(AuUInt64 uTimeout)
|
bool RWLockImpl<bIsWriteRecursionAllowed>::LockReadNS(AuUInt64 uTimeout)
|
||||||
{
|
{
|
||||||
|
AuInt32 iCurState {};
|
||||||
|
bool bRet {};
|
||||||
|
|
||||||
if (this->TryLockReadNoSpin<true>())
|
if (this->TryLockReadNoSpin<true>())
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -224,7 +241,8 @@ namespace Aurora::Threading::Primitives
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
AuInt32 iCurState {};
|
auto pCounter = this->GetReadSleepCounter();
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
iCurState = this->state_;
|
iCurState = this->state_;
|
||||||
@ -233,7 +251,11 @@ namespace Aurora::Threading::Primitives
|
|||||||
{
|
{
|
||||||
if (gUseFutexRWLock)
|
if (gUseFutexRWLock)
|
||||||
{
|
{
|
||||||
if (!InternalLTSWaitOnAddressHighRes((const void *)&this->state_, &iCurState, sizeof(iCurState), uEndTime))
|
AuAtomicAdd(pCounter, 1u);
|
||||||
|
bRet = InternalLTSWaitOnAddressHighRes((const void *)&this->state_, &iCurState, sizeof(iCurState), uEndTime);
|
||||||
|
AuAtomicSub(pCounter, 1u);
|
||||||
|
|
||||||
|
if (!bRet)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -331,6 +353,9 @@ namespace Aurora::Threading::Primitives
|
|||||||
bool RWLockImpl<bIsWriteRecursionAllowed>::LockWriteNSAbsSecondPath()
|
bool RWLockImpl<bIsWriteRecursionAllowed>::LockWriteNSAbsSecondPath()
|
||||||
{
|
{
|
||||||
auto uOld = this->state_;
|
auto uOld = this->state_;
|
||||||
|
|
||||||
|
if constexpr (bIsWriteRecursionAllowed)
|
||||||
|
{
|
||||||
if (uOld < 0)
|
if (uOld < 0)
|
||||||
{
|
{
|
||||||
if (this->reentrantWriteLockHandle_ == GetThreadCookie())
|
if (this->reentrantWriteLockHandle_ == GetThreadCookie())
|
||||||
@ -339,7 +364,9 @@ namespace Aurora::Threading::Primitives
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (uOld == 0)
|
}
|
||||||
|
|
||||||
|
if (uOld == 0)
|
||||||
{
|
{
|
||||||
if (AuAtomicCompareExchange(&this->state_, -1, uOld) == uOld)
|
if (AuAtomicCompareExchange(&this->state_, -1, uOld) == uOld)
|
||||||
{
|
{
|
||||||
@ -354,6 +381,9 @@ namespace Aurora::Threading::Primitives
|
|||||||
template<bool bIsWriteRecursionAllowed>
|
template<bool bIsWriteRecursionAllowed>
|
||||||
bool RWLockImpl<bIsWriteRecursionAllowed>::LockWriteNS(AuUInt64 uTimeout)
|
bool RWLockImpl<bIsWriteRecursionAllowed>::LockWriteNS(AuUInt64 uTimeout)
|
||||||
{
|
{
|
||||||
|
bool bRet {};
|
||||||
|
AuInt64 uEndTime {};
|
||||||
|
|
||||||
if constexpr (!bIsWriteRecursionAllowed)
|
if constexpr (!bIsWriteRecursionAllowed)
|
||||||
{
|
{
|
||||||
if (this->TryLockWrite())
|
if (this->TryLockWrite())
|
||||||
@ -363,27 +393,12 @@ namespace Aurora::Threading::Primitives
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto uOld = AuAtomicLoad(&this->state_);
|
if (this->LockWriteNSAbsSecondPath())
|
||||||
if (uOld < 0)
|
|
||||||
{
|
{
|
||||||
if (this->reentrantWriteLockHandle_ == GetThreadCookie())
|
|
||||||
{
|
|
||||||
AuAtomicSub(&this->state_, 1);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (uOld == 0)
|
|
||||||
{
|
|
||||||
if (AuAtomicCompareExchange(&this->state_, -1, uOld) == uOld)
|
|
||||||
{
|
|
||||||
this->reentrantWriteLockHandle_ = GetThreadCookie();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bRet {};
|
|
||||||
AuInt64 uEndTime {};
|
|
||||||
AuAtomicAdd(&this->writersPending_, 1);
|
AuAtomicAdd(&this->writersPending_, 1);
|
||||||
|
|
||||||
if (gUseFutexRWLock)
|
if (gUseFutexRWLock)
|
||||||
@ -411,17 +426,17 @@ namespace Aurora::Threading::Primitives
|
|||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
bool bStatus {};
|
||||||
AuInt32 iCurState;
|
AuInt32 iCurState;
|
||||||
|
|
||||||
while ((iCurState = AuAtomicLoad(&this->state_)) != 0)
|
while ((iCurState = AuAtomicLoad(&this->state_)) != 0)
|
||||||
{
|
{
|
||||||
AuInt64 uSecondTimeout = 0;
|
AuInt64 uSecondTimeout = 0;
|
||||||
|
|
||||||
bool bStatus {};
|
|
||||||
if (gUseFutexRWLock)
|
if (gUseFutexRWLock)
|
||||||
{
|
{
|
||||||
auto pSemaphore = this->GetFutexConditionWriter();
|
auto pSemaphore = this->GetFutexConditionWriter();
|
||||||
|
|
||||||
AuInt32 iCurState;
|
|
||||||
while ((iCurState = AuAtomicLoad(&this->state_)) != 0)
|
while ((iCurState = AuAtomicLoad(&this->state_)) != 0)
|
||||||
{
|
{
|
||||||
static const AuUInt32 kExpect { 0 };
|
static const AuUInt32 kExpect { 0 };
|
||||||
@ -531,9 +546,12 @@ namespace Aurora::Threading::Primitives
|
|||||||
void RWLockImpl<bIsWriteRecursionAllowed>::SignalManyReader()
|
void RWLockImpl<bIsWriteRecursionAllowed>::SignalManyReader()
|
||||||
{
|
{
|
||||||
if (gUseFutexRWLock)
|
if (gUseFutexRWLock)
|
||||||
|
{
|
||||||
|
if (AuAtomicLoad(this->GetReadSleepCounter()))
|
||||||
{
|
{
|
||||||
InternalLTSWakeAll((const void *)&this->state_);
|
InternalLTSWakeAll((const void *)&this->state_);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->GetCondition().Broadcast();
|
this->GetCondition().Broadcast();
|
||||||
|
@ -97,6 +97,7 @@ namespace Aurora::Threading::Primitives
|
|||||||
auline void SignalManyReader();
|
auline void SignalManyReader();
|
||||||
auline void SignalManyWriter(int iBias = 0);
|
auline void SignalManyWriter(int iBias = 0);
|
||||||
|
|
||||||
|
auline AuUInt32 *GetReadSleepCounter();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
RWLockAccessView<true, RWLockImpl> read_;
|
RWLockAccessView<true, RWLockImpl> read_;
|
||||||
|
Loading…
Reference in New Issue
Block a user