[*] RWLock improvements

This commit is contained in:
Reece Wilson 2023-07-30 11:10:08 +01:00
parent 8bede175e3
commit 9a2e5674e8
2 changed files with 58 additions and 42 deletions

View File

@ -18,6 +18,8 @@ namespace Aurora::Threading::Primitives
#define ViewParent ((T *)(((char *)this) - (bIsReadView ? RWLockImpl<true>::kOffsetOfRead : RWLockImpl<true>::kOffsetOfWrite))) #define ViewParent ((T *)(((char *)this) - (bIsReadView ? RWLockImpl<true>::kOffsetOfRead : RWLockImpl<true>::kOffsetOfWrite)))
#endif #endif
static const auto kRWThreadWriterHardContextSwitchBias = 15;
template<bool bIsReadView, typename T> template<bool bIsReadView, typename T>
void RWLockAccessView<bIsReadView, T>::Unlock() void RWLockAccessView<bIsReadView, T>::Unlock()
{ {
@ -152,12 +154,6 @@ namespace Aurora::Threading::Primitives
{ {
return false; return false;
} }
if (this->writersPending_)
{
this->GetConditionWriter().Broadcast();
continue;
}
} }
} }
} }
@ -198,8 +194,9 @@ namespace Aurora::Threading::Primitives
} }
} }
AuAtomicAdd(&this->writersPending_, 1);
AU_LOCK_GUARD(this->mutex_); AU_LOCK_GUARD(this->mutex_);
this->writersPending_++;
AuInt64 uEndTime = uTimeout ? AuTime::SteadyClockNS() + uTimeout : 0; AuInt64 uEndTime = uTimeout ? AuTime::SteadyClockNS() + uTimeout : 0;
@ -215,7 +212,7 @@ namespace Aurora::Threading::Primitives
if (uSecondTimeout <= 0) if (uSecondTimeout <= 0)
{ {
this->writersPending_--; AuAtomicSub(&this->writersPending_, 1);
return false; return false;
} }
} }
@ -226,7 +223,7 @@ namespace Aurora::Threading::Primitives
if (!this->GetConditionWriter().WaitForSignalNsEx(AuUnsafeRaiiToShared(&this->mutex_), uSecondTimeout)) if (!this->GetConditionWriter().WaitForSignalNsEx(AuUnsafeRaiiToShared(&this->mutex_), uSecondTimeout))
#endif #endif
{ {
this->writersPending_--; AuAtomicSub(&this->writersPending_, 1);
return false; return false;
} }
} }
@ -234,12 +231,13 @@ namespace Aurora::Threading::Primitives
if (AuAtomicCompareExchange(&this->state_, -1, 0) == 0) if (AuAtomicCompareExchange(&this->state_, -1, 0) == 0)
{ {
this->reentrantWriteLockHandle_ = GetThreadCookie(); this->reentrantWriteLockHandle_ = GetThreadCookie();
this->writersPending_--; AuAtomicSub(&this->writersPending_, 1);
return true; return true;
} }
else else
{ {
this->GetConditionWriter().Broadcast(); this->GetConditionWriter().Broadcast();
this->GetCondition().Broadcast();
} }
} }
@ -265,7 +263,7 @@ namespace Aurora::Threading::Primitives
template<bool bIsWriteRecursionAllowed> template<bool bIsWriteRecursionAllowed>
bool RWLockImpl<bIsWriteRecursionAllowed>::TryLockWrite() bool RWLockImpl<bIsWriteRecursionAllowed>::TryLockWrite()
{ {
for (AuUInt i = 0; i < 20; i++) for (AU_ITERATE_N(i, kRWThreadWriterHardContextSwitchBias))
{ {
auto curVal = this->state_; auto curVal = this->state_;
@ -309,61 +307,82 @@ namespace Aurora::Threading::Primitives
template<bool bIsWriteRecursionAllowed> template<bool bIsWriteRecursionAllowed>
void RWLockImpl<bIsWriteRecursionAllowed>::UnlockRead() void RWLockImpl<bIsWriteRecursionAllowed>::UnlockRead()
{ {
AuInt32 uVal {};
if (this->state_ < 0) if (this->state_ < 0)
{ {
SysAssertDbg(this->reentrantWriteLockHandle_ == GetThreadCookie()); SysAssertDbg(this->reentrantWriteLockHandle_ == GetThreadCookie());
return; return;
} }
AuInt32 val {}; uVal = AuAtomicSub(&this->state_, 1);
bool bElevation {};
if (uVal == 0)
{ {
AU_LOCK_GUARD(this->mutex_); bool bElevation {};
val = AuAtomicSub(&this->state_, 1);
bElevation = this->bElevaterPending_; {
} AU_LOCK_GUARD(this->mutex_);
bElevation = this->writersPending_ > 0;
}
if ((val == 0) && (bElevation)) if (bElevation)
{ {
this->GetConditionWriter().Signal(); this->GetConditionWriter().Signal();
} }
else
if (val == 0) {
{ this->GetCondition().Broadcast();
this->GetCondition().Signal(); }
this->GetConditionWriter().Signal();
} }
} }
template<bool bIsWriteRecursionAllowed> template<bool bIsWriteRecursionAllowed>
void RWLockImpl<bIsWriteRecursionAllowed>::UnlockWrite() void RWLockImpl<bIsWriteRecursionAllowed>::UnlockWrite()
{ {
bool bElevationPending {};
if constexpr (!bIsWriteRecursionAllowed) if constexpr (!bIsWriteRecursionAllowed)
{ {
this->reentrantWriteLockHandle_ = 0;
{ {
AU_LOCK_GUARD(this->mutex_); AU_LOCK_GUARD(this->mutex_);
this->reentrantWriteLockHandle_ = 0;
this->state_ = 0; this->state_ = 0;
bElevationPending = this->writersPending_ > 0;
} }
this->GetConditionWriter().Broadcast(); if (bElevationPending)
this->GetCondition().Broadcast(); {
this->GetConditionWriter().Signal();
}
else
{
this->GetCondition().Broadcast();
}
} }
else else
{ {
AuInt32 val {}; AuInt32 val {};
{ this->reentrantWriteLockHandle_ = 0;
AU_LOCK_GUARD(this->mutex_); val = AuAtomicAdd(&this->state_, 1);
val = AuAtomicAdd(&this->state_, 1);
this->reentrantWriteLockHandle_ = 0;
}
if (val == 0) if (val == 0)
{ {
this->GetConditionWriter().Broadcast(); {
this->GetCondition().Broadcast(); AU_LOCK_GUARD(this->mutex_);
bElevationPending = this->writersPending_ > 0;
}
if (bElevationPending)
{
this->GetConditionWriter().Signal();
}
else
{
this->GetCondition().Broadcast();
}
} }
} }
} }
@ -375,7 +394,7 @@ namespace Aurora::Threading::Primitives
while (this->state_ != 1) while (this->state_ != 1)
{ {
this->bElevaterPending_ = true; AuAtomicAdd(&this->writersPending_, 1);
if (!this->GetConditionWriter().WaitForSignal(timeout)) if (!this->GetConditionWriter().WaitForSignal(timeout))
{ {
@ -383,7 +402,7 @@ namespace Aurora::Threading::Primitives
} }
} }
this->bElevaterPending_ = false; AuAtomicSub(&this->writersPending_, 1);
this->reentrantWriteLockHandle_ = GetThreadCookie(); this->reentrantWriteLockHandle_ = GetThreadCookie();
this->state_ = -1; this->state_ = -1;
return true; return true;

View File

@ -93,10 +93,7 @@ namespace Aurora::Threading::Primitives
#endif #endif
ThreadCookie_t reentrantWriteLockHandle_ {}; ThreadCookie_t reentrantWriteLockHandle_ {};
volatile AuInt32 state_ {}; volatile AuInt32 state_ {};
AuInt32 writersPending_ : 31 {}; AuInt32 writersPending_ {};
AuInt32 bElevaterPending_ : 1 {};
//bool bElevaterPending_{};
//bool reentrantWriteLock_ {true};
public: public:
cstatic const AuUInt8 kOffsetOfRead = AuOffsetOf(&RWLockImpl::read_); cstatic const AuUInt8 kOffsetOfRead = AuOffsetOf(&RWLockImpl::read_);