From 5cc811be1999126245f47d1ce22775f3f9eac199 Mon Sep 17 00:00:00 2001 From: Jamie Reece Wilson Date: Mon, 21 Aug 2023 17:34:24 +0100 Subject: [PATCH] [*] More compact Win32 primitives! --- .../Threading/Primitives/SOOPrimitives.hpp | 12 ++-- Source/Threading/AuWakeOnAddress.cpp | 7 +- Source/Threading/AuWakeOnAddress.hpp | 4 +- .../Primitives/AuConditionMutex.NT.cpp | 6 +- .../Primitives/AuConditionMutex.NT.hpp | 39 +++++++++-- .../Primitives/AuConditionVariable.NT.cpp | 40 ++---------- .../Primitives/AuConditionVariable.NT.hpp | 65 +++++++++++++------ Source/Threading/Primitives/AuEvent.cpp | 5 +- Source/Threading/Primitives/AuEvent.hpp | 4 +- Source/Threading/Primitives/AuRWLock.cpp | 18 ++--- Source/Threading/Primitives/AuRWLock.hpp | 10 +-- .../Threading/Primitives/AuSemaphore.NT.cpp | 8 +-- .../Threading/Primitives/AuSemaphore.NT.hpp | 4 +- 13 files changed, 121 insertions(+), 101 deletions(-) diff --git a/Include/Aurora/Threading/Primitives/SOOPrimitives.hpp b/Include/Aurora/Threading/Primitives/SOOPrimitives.hpp index 0c3dfb31..943e3aed 100644 --- a/Include/Aurora/Threading/Primitives/SOOPrimitives.hpp +++ b/Include/Aurora/Threading/Primitives/SOOPrimitives.hpp @@ -20,18 +20,18 @@ namespace Aurora::Threading::Primitives #if defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86) static const auto kPrimitiveSize64NTMutex = 16; - static const auto kPrimitiveSize64NTSemaphore = 64; + static const auto kPrimitiveSize64NTSemaphore = 24; static const auto kPrimitiveSize64NTCS = 32; - static const auto kPrimitiveSize64NTEvent = 64; - static const auto kPrimitiveSize64NTRWLock = 88; + static const auto kPrimitiveSize64NTEvent = 24; + static const auto kPrimitiveSize64NTRWLock = 56; static const auto kPrimitiveSize64NTCond = 32; static const auto kPrimitiveSize64NTCondMutex = 16; static const auto kPrimitiveSize32NTMutex = 8; - static const auto kPrimitiveSize32NTSemaphore = 36; + static const auto kPrimitiveSize32NTSemaphore = 20; static const auto kPrimitiveSize32NTCS = 20; - static const auto kPrimitiveSize32NTEvent = 36; - static const auto kPrimitiveSize32NTRWLock = 56; + static const auto kPrimitiveSize32NTEvent = 20; + static const auto kPrimitiveSize32NTRWLock = 44; static const auto kPrimitiveSize32NTCond = 20; static const auto kPrimitiveSize32NTCondMutex = 8; diff --git a/Source/Threading/AuWakeOnAddress.cpp b/Source/Threading/AuWakeOnAddress.cpp index c83b4c90..e7705caf 100644 --- a/Source/Threading/AuWakeOnAddress.cpp +++ b/Source/Threading/AuWakeOnAddress.cpp @@ -96,8 +96,7 @@ namespace Aurora::Threading AuResetMember(this->pAddress); } - WaitEntry::WaitEntry() : - variable(AuUnsafeRaiiToShared(&this->mutex)) + WaitEntry::WaitEntry() { } @@ -134,7 +133,7 @@ namespace Aurora::Threading Win32DropSchedulerResolution(); #endif - this->variable.WaitForSignalNS(uTimeRemNS); + this->variable.WaitForSignalNsEx(&this->mutex, uTimeRemNS); uNow = AuTime::SteadyClockNS(); } @@ -145,7 +144,7 @@ namespace Aurora::Threading { while (WaitBuffer::From(this->pAddress, this->uSize).Compare(state)) { - this->variable.WaitForSignal(0); + this->variable.WaitForSignalNsEx(&this->mutex, 0); } return true; diff --git a/Source/Threading/AuWakeOnAddress.hpp b/Source/Threading/AuWakeOnAddress.hpp index 48da5dec..fa8cab9e 100644 --- a/Source/Threading/AuWakeOnAddress.hpp +++ b/Source/Threading/AuWakeOnAddress.hpp @@ -45,8 +45,8 @@ namespace Aurora::Threading // synch AuUInt32 uAtomic {}; // fastpath - Primitives::ConditionMutexImpl mutex; // mutex ctor must come before var - Primitives::ConditionVariableImpl variable; // ...and something all 2007+ micro and monolithic kernels should have to yield for an event + Primitives::ConditionMutexInternal mutex; // mutex ctor must come before var + Primitives::ConditionVariableInternal variable; // ...and something all 2007+ micro and monolithic kernels should have to yield for an event // state const void *pAddress {}; diff --git a/Source/Threading/Primitives/AuConditionMutex.NT.cpp b/Source/Threading/Primitives/AuConditionMutex.NT.cpp index 65348fb4..d3208f75 100644 --- a/Source/Threading/Primitives/AuConditionMutex.NT.cpp +++ b/Source/Threading/Primitives/AuConditionMutex.NT.cpp @@ -181,15 +181,15 @@ namespace Aurora::Threading::Primitives AUKN_SYM IConditionMutex *ConditionMutexNew() { - return _new Win32ConditionMutex(); + return _new ConditionMutexImpl(); } AUKN_SYM void ConditionMutexRelease(IConditionMutex *pMutex) { - AuSafeDelete(pMutex); + AuSafeDelete(pMutex); } - AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, ConditionMutex, Win32ConditionMutex) + AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, ConditionMutex, ConditionMutexImpl) } #endif \ No newline at end of file diff --git a/Source/Threading/Primitives/AuConditionMutex.NT.hpp b/Source/Threading/Primitives/AuConditionMutex.NT.hpp index 351d898d..6e48566d 100644 --- a/Source/Threading/Primitives/AuConditionMutex.NT.hpp +++ b/Source/Threading/Primitives/AuConditionMutex.NT.hpp @@ -30,15 +30,15 @@ namespace Aurora::Threading::Primitives volatile AuUInt32 uWaitCount {}; // yields while bits are high, dec to release one from the semaphore yield }; - struct Win32ConditionMutex final : IConditionMutexEx + struct Win32ConditionMutex final { Win32ConditionMutex(); ~Win32ConditionMutex(); - auline bool TryLock() override; - auline void Lock() override; - auline void Unlock() override; - AuUInt GetOSHandle() override; + bool TryLock(); + void Lock(); + void Unlock(); + AuUInt GetOSHandle(); auline bool TryLockNoSpin(); auline bool TryLockHeavy(); @@ -49,7 +49,32 @@ namespace Aurora::Threading::Primitives SRWLOCK lock_; #endif }; - - using ConditionMutexImpl = Win32ConditionMutex; + + using ConditionMutexInternal = Win32ConditionMutex; + + struct ConditionMutexImpl final : IConditionMutexEx + { + auline bool TryLock() + { + return mutex.TryLock(); + } + + auline void Lock() + { + mutex.Unlock(); + } + + auline void Unlock() + { + mutex.Unlock(); + } + + inline AuUInt GetOSHandle() + { + return mutex.GetOSHandle(); + } + + ConditionMutexInternal mutex; + }; } #endif \ No newline at end of file diff --git a/Source/Threading/Primitives/AuConditionVariable.NT.cpp b/Source/Threading/Primitives/AuConditionVariable.NT.cpp index 9ee2c8bb..451de92f 100644 --- a/Source/Threading/Primitives/AuConditionVariable.NT.cpp +++ b/Source/Threading/Primitives/AuConditionVariable.NT.cpp @@ -19,42 +19,14 @@ namespace Aurora::Threading::Primitives { - ConditionVariableImpl::ConditionVariableImpl(const AuSPtr &pMutex) : - mutex_(AuStaticCast(pMutex)) + ConditionVariableNT::ConditionVariableNT() { #if defined(AURORA_FORCE_SRW_LOCKS) ::InitializeConditionVariable(&this->winCond_); #endif } - - AuSPtr ConditionVariableImpl::GetMutex() - { - return this->mutex_; - } - - bool ConditionVariableImpl::WaitForSignal(AuUInt32 uTimeout) - { - #if !defined(AURORA_FORCE_SRW_LOCKS) - return WaitForSignalNS(AuMSToNS(uTimeout)); - #else - auto bOK = ::SleepConditionVariableSRW(&this->winCond_, reinterpret_cast(this->mutex_->GetOSHandle()), uTimeout ? uTimeout : INFINITE, 0); - - if (!bOK) - { - SysAssert(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariable failure"); - return false; - } - - return true; - #endif - } - - bool ConditionVariableImpl::WaitForSignalNS(AuUInt64 qwTimeout) - { - return this->WaitForSignalNsEx(this->mutex_, qwTimeout); - } - - bool ConditionVariableImpl::WaitForSignalNsEx(const std::shared_ptr &pMutex, AuUInt64 qwTimeout) + + bool ConditionVariableNT::WaitForSignalNsEx(Win32ConditionMutex *pMutex, AuUInt64 qwTimeout) { #if !defined(AURORA_FORCE_SRW_LOCKS) bool bRet { true }; @@ -309,7 +281,7 @@ namespace Aurora::Threading::Primitives #endif } - bool ConditionVariableImpl::CheckOut() + bool ConditionVariableNT::CheckOut() { #if defined(AURORA_FORCE_SRW_LOCKS) return false; @@ -343,7 +315,7 @@ namespace Aurora::Threading::Primitives #endif } - void ConditionVariableImpl::Signal() + void ConditionVariableNT::Signal() { #if !defined(AURORA_FORCE_SRW_LOCKS) auto original = this->wlist; @@ -379,7 +351,7 @@ namespace Aurora::Threading::Primitives #endif } - void ConditionVariableImpl::Broadcast() + void ConditionVariableNT::Broadcast() { #if !defined(AURORA_FORCE_SRW_LOCKS) diff --git a/Source/Threading/Primitives/AuConditionVariable.NT.hpp b/Source/Threading/Primitives/AuConditionVariable.NT.hpp index a80d84d5..7b90d932 100644 --- a/Source/Threading/Primitives/AuConditionVariable.NT.hpp +++ b/Source/Threading/Primitives/AuConditionVariable.NT.hpp @@ -12,16 +12,13 @@ namespace Aurora::Threading::Primitives { - struct ConditionVariableImpl final : IConditionVariable + struct ConditionVariableNT final { - ConditionVariableImpl(const AuSPtr &mutex); + ConditionVariableNT(); - auline AuSPtr GetMutex() override; - auline bool WaitForSignal(AuUInt32 timeout) override; - bool WaitForSignalNsEx(const std::shared_ptr &pMutex, AuUInt64 timeout); - bool WaitForSignalNS(AuUInt64 qwTimeout) override; - auline void Signal() override; - auline void Broadcast() override; + bool WaitForSignalNsEx(Win32ConditionMutex *pMutex, AuUInt64 timeout); + void Signal(); + void Broadcast(); auline bool CheckOut(); @@ -32,22 +29,52 @@ namespace Aurora::Threading::Primitives AuUInt32 wlist {}; AuUInt32 signalCount {}; #endif - - std::shared_ptr mutex_; }; - struct CondVarDummy : IConditionVariable + using ConditionVariableInternal = ConditionVariableNT; + + struct ConditionVariableImpl final : IConditionVariable { - private: - #if defined(AURORA_FORCE_SRW_LOCKS) - CONDITION_VARIABLE winCond_; - #else - AuUInt32 wlist {}; - AuUInt32 signalCount {}; - #endif + inline ConditionVariableImpl(const AuSPtr &mutex) : + mutex(mutex) + { + } + + auline AuSPtr GetMutex() override + { + return mutex; + } + + auline bool WaitForSignal(AuUInt32 timeout) override + { + return cond.WaitForSignalNsEx(&std::static_pointer_cast(this->mutex)->mutex, AuMSToNS(timeout)); + } + + auline bool WaitForSignalNS(AuUInt64 qwTimeout) override + { + return cond.WaitForSignalNsEx(&std::static_pointer_cast(this->mutex)->mutex, qwTimeout); + } + + inline bool WaitForSignalNsEx(const std::shared_ptr &pMutex, AuUInt64 timeout) + { + return cond.WaitForSignalNsEx(pMutex.get(), timeout); + } + + auline void Signal() override + { + cond.Signal(); + } + + auline void Broadcast() override + { + cond.Broadcast(); + } + + ConditionVariableNT cond; + std::shared_ptr mutex; }; - static const auto kSizeOfDummyCondVar = sizeof(CondVarDummy); + static const auto kSizeOfDummyCondVar = sizeof(ConditionVariableInternal); static const auto kBoolRequiredLateSet = true; diff --git a/Source/Threading/Primitives/AuEvent.cpp b/Source/Threading/Primitives/AuEvent.cpp index 740d4c1e..897fc461 100644 --- a/Source/Threading/Primitives/AuEvent.cpp +++ b/Source/Threading/Primitives/AuEvent.cpp @@ -14,8 +14,7 @@ namespace Aurora::Threading::Primitives EventImpl::EventImpl(bool bTriggered, bool bAtomicRelease, bool bPermitMultipleTriggers) : bTriggered_(bTriggered), bAtomicRelease_(bAtomicRelease), - bPermitMultipleTriggers_(bPermitMultipleTriggers), - condition_(AuUnsafeRaiiToShared(&this->mutex_)) + bPermitMultipleTriggers_(bPermitMultipleTriggers) {} EventImpl::~EventImpl() {} @@ -58,7 +57,7 @@ namespace Aurora::Threading::Primitives uTimeoutNS = uEndTime - uStartTime; } - if (!this->condition_.WaitForSignalNS(uTimeoutNS)) + if (!this->condition_.WaitForSignalNsEx(&this->mutex_, uTimeoutNS)) { continue; } diff --git a/Source/Threading/Primitives/AuEvent.hpp b/Source/Threading/Primitives/AuEvent.hpp index 1d8de624..9776203c 100644 --- a/Source/Threading/Primitives/AuEvent.hpp +++ b/Source/Threading/Primitives/AuEvent.hpp @@ -31,8 +31,8 @@ namespace Aurora::Threading::Primitives private: bool AtomicIsEventSetLogic(); - ConditionMutexImpl mutex_; // must come first - ConditionVariableImpl condition_; + ConditionMutexInternal mutex_; // must come first + ConditionVariableInternal condition_; #if 0 const bool bAtomicRelease_ {}; diff --git a/Source/Threading/Primitives/AuRWLock.cpp b/Source/Threading/Primitives/AuRWLock.cpp index 8c27d201..b0f38dbd 100644 --- a/Source/Threading/Primitives/AuRWLock.cpp +++ b/Source/Threading/Primitives/AuRWLock.cpp @@ -119,20 +119,20 @@ namespace Aurora::Threading::Primitives } template - ConditionVariableImpl &RWLockImpl::GetCondition() + ConditionVariableInternal &RWLockImpl::GetCondition() { #if !defined(AURWLOCK_NO_SIZE_OPTIMIZED_CONDVAR) - return *(ConditionVariableImpl *)this->conditionVariable_; + return *(ConditionVariableInternal *)this->conditionVariable_; #else return this->condition_; #endif } template - ConditionVariableImpl &RWLockImpl::GetConditionWriter() + ConditionVariableInternal &RWLockImpl::GetConditionWriter() { #if !defined(AURWLOCK_NO_SIZE_OPTIMIZED_CONDVAR) - return *(ConditionVariableImpl *)this->conditionVariableWriter_; + return *(ConditionVariableInternal *)this->conditionVariableWriter_; #else return this->conditionWriter_; #endif @@ -173,7 +173,7 @@ namespace Aurora::Threading::Primitives #if defined(AURWLOCK_NO_SIZE_OPTIMIZED_CONDVAR) if (!this->GetCondition().WaitForSignalNS(iSecondTimeout)) #else - if (!this->GetCondition().WaitForSignalNsEx(AuUnsafeRaiiToShared(&this->mutex_), iSecondTimeout)) + if (!this->GetCondition().WaitForSignalNsEx(&this->mutex_, iSecondTimeout)) #endif { return false; @@ -229,7 +229,7 @@ namespace Aurora::Threading::Primitives #if defined(AURWLOCK_NO_SIZE_OPTIMIZED_CONDVAR) if (!this->GetCondition().WaitForSignalNS(iSecondTimeout)) #else - if (!this->GetCondition().WaitForSignalNsEx(AuUnsafeRaiiToShared(&this->mutex_), iSecondTimeout)) + if (!this->GetCondition().WaitForSignalNsEx(&this->mutex_, iSecondTimeout)) #endif { return false; @@ -297,7 +297,7 @@ namespace Aurora::Threading::Primitives #if defined(AURWLOCK_NO_SIZE_OPTIMIZED_CONDVAR) bool bStatus = this->GetConditionWriter().WaitForSignalNS(iSecondTimeout); #else - bool bStatus = this->GetConditionWriter().WaitForSignalNsEx(AuUnsafeRaiiToShared(&this->mutex_), iSecondTimeout); + bool bStatus = this->GetConditionWriter().WaitForSignalNsEx(&this->mutex_, iSecondTimeout); #endif if constexpr (bIsWriteRecursionAllowed) @@ -382,7 +382,7 @@ namespace Aurora::Threading::Primitives #if defined(AURWLOCK_NO_SIZE_OPTIMIZED_CONDVAR) bool bStatus = this->GetConditionWriter().WaitForSignalNS(uSecondTimeout); #else - bool bStatus = this->GetConditionWriter().WaitForSignalNsEx(AuUnsafeRaiiToShared(&this->mutex_), uSecondTimeout); + bool bStatus = this->GetConditionWriter().WaitForSignalNsEx(&this->mutex_, uSecondTimeout); #endif if constexpr (bIsWriteRecursionAllowed) @@ -624,7 +624,7 @@ namespace Aurora::Threading::Primitives #if defined(AURWLOCK_NO_SIZE_OPTIMIZED_CONDVAR) if (!this->GetConditionWriter().WaitForSignalNS(iSecondTimeout)) #else - if (!this->GetConditionWriter().WaitForSignalNsEx(AuUnsafeRaiiToShared(&this->mutex_), iSecondTimeout)) + if (!this->GetConditionWriter().WaitForSignalNsEx(&this->mutex_, iSecondTimeout)) #endif { return false; diff --git a/Source/Threading/Primitives/AuRWLock.hpp b/Source/Threading/Primitives/AuRWLock.hpp index bbda622c..97cf5534 100644 --- a/Source/Threading/Primitives/AuRWLock.hpp +++ b/Source/Threading/Primitives/AuRWLock.hpp @@ -80,18 +80,18 @@ namespace Aurora::Threading::Primitives IWaitable *AsReadable() override; IWaitable *AsWritable() override; - auline ConditionVariableImpl &GetCondition(); - auline ConditionVariableImpl &GetConditionWriter(); + auline ConditionVariableInternal &GetCondition(); + auline ConditionVariableInternal &GetConditionWriter(); private: RWLockAccessView read_; RWLockAccessView write_; - ConditionMutexImpl mutex_; + ConditionMutexInternal mutex_; #if defined(AURWLOCK_NO_SIZE_OPTIMIZED_CONDVAR) - ConditionVariableImpl condition_; - ConditionVariableImpl conditionWriter_; + ConditionVariableInternal condition_; + ConditionVariableInternal conditionWriter_; #else char conditionVariable_[kSizeOfDummyCondVar] {}; char conditionVariableWriter_[kSizeOfDummyCondVar] {}; diff --git a/Source/Threading/Primitives/AuSemaphore.NT.cpp b/Source/Threading/Primitives/AuSemaphore.NT.cpp index 35300398..1b7ce59c 100644 --- a/Source/Threading/Primitives/AuSemaphore.NT.cpp +++ b/Source/Threading/Primitives/AuSemaphore.NT.cpp @@ -15,15 +15,13 @@ namespace Aurora::Threading::Primitives { - SemaphoreImpl::SemaphoreImpl(AuUInt16 uIntialValue) : - var(AuUnsafeRaiiToShared(&this->mutex)) + SemaphoreImpl::SemaphoreImpl(AuUInt16 uIntialValue) { this->dwState_ = uIntialValue; } SemaphoreImpl::~SemaphoreImpl() { - } bool SemaphoreImpl::HasOSHandle(AuMach &mach) @@ -110,11 +108,11 @@ namespace Aurora::Threading::Primitives return false; } - var.WaitForSignalNS(uEnd - uStart); + var.WaitForSignalNsEx(&this->mutex, uEnd - uStart); } else { - var.WaitForSignalNS(0); + var.WaitForSignalNsEx(&this->mutex, 0); } } diff --git a/Source/Threading/Primitives/AuSemaphore.NT.hpp b/Source/Threading/Primitives/AuSemaphore.NT.hpp index 4a70c281..0ef51e8e 100644 --- a/Source/Threading/Primitives/AuSemaphore.NT.hpp +++ b/Source/Threading/Primitives/AuSemaphore.NT.hpp @@ -31,7 +31,7 @@ namespace Aurora::Threading::Primitives private: AuUInt32 dwState_ {}; - ConditionMutexImpl mutex; - ConditionVariableImpl var; + ConditionMutexInternal mutex; + ConditionVariableInternal var; }; } \ No newline at end of file