[*] More compact Win32 primitives!

This commit is contained in:
Reece Wilson 2023-08-21 17:34:24 +01:00
parent 869512e651
commit 5cc811be19
13 changed files with 121 additions and 101 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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 {};

View File

@ -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<Win32ConditionMutex *>(pMutex);
AuSafeDelete<ConditionMutexImpl *>(pMutex);
}
AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, ConditionMutex, Win32ConditionMutex)
AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, ConditionMutex, ConditionMutexImpl)
}
#endif

View File

@ -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();
@ -50,6 +50,31 @@ namespace Aurora::Threading::Primitives
#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

View File

@ -19,42 +19,14 @@
namespace Aurora::Threading::Primitives
{
ConditionVariableImpl::ConditionVariableImpl(const AuSPtr<IConditionMutex> &pMutex) :
mutex_(AuStaticCast<Win32ConditionMutex>(pMutex))
ConditionVariableNT::ConditionVariableNT()
{
#if defined(AURORA_FORCE_SRW_LOCKS)
::InitializeConditionVariable(&this->winCond_);
#endif
}
AuSPtr<IConditionMutex> ConditionVariableImpl::GetMutex()
{
return this->mutex_;
}
bool ConditionVariableImpl::WaitForSignal(AuUInt32 uTimeout)
{
#if !defined(AURORA_FORCE_SRW_LOCKS)
return WaitForSignalNS(AuMSToNS<AuUInt64>(uTimeout));
#else
auto bOK = ::SleepConditionVariableSRW(&this->winCond_, reinterpret_cast<PSRWLOCK>(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<Win32ConditionMutex> &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)

View File

@ -12,16 +12,13 @@
namespace Aurora::Threading::Primitives
{
struct ConditionVariableImpl final : IConditionVariable
struct ConditionVariableNT final
{
ConditionVariableImpl(const AuSPtr<IConditionMutex> &mutex);
ConditionVariableNT();
auline AuSPtr<IConditionMutex> GetMutex() override;
auline bool WaitForSignal(AuUInt32 timeout) override;
bool WaitForSignalNsEx(const std::shared_ptr<Win32ConditionMutex> &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<Win32ConditionMutex> 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<IConditionMutex> &mutex) :
mutex(mutex)
{
}
auline AuSPtr<IConditionMutex> GetMutex() override
{
return mutex;
}
auline bool WaitForSignal(AuUInt32 timeout) override
{
return cond.WaitForSignalNsEx(&std::static_pointer_cast<ConditionMutexImpl>(this->mutex)->mutex, AuMSToNS<AuUInt64>(timeout));
}
auline bool WaitForSignalNS(AuUInt64 qwTimeout) override
{
return cond.WaitForSignalNsEx(&std::static_pointer_cast<ConditionMutexImpl>(this->mutex)->mutex, qwTimeout);
}
inline bool WaitForSignalNsEx(const std::shared_ptr<Win32ConditionMutex> &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<IConditionMutex> mutex;
};
static const auto kSizeOfDummyCondVar = sizeof(CondVarDummy);
static const auto kSizeOfDummyCondVar = sizeof(ConditionVariableInternal);
static const auto kBoolRequiredLateSet = true;

View File

@ -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;
}

View File

@ -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_ {};

View File

@ -119,20 +119,20 @@ namespace Aurora::Threading::Primitives
}
template<bool bIsWriteRecursionAllowed>
ConditionVariableImpl &RWLockImpl<bIsWriteRecursionAllowed>::GetCondition()
ConditionVariableInternal &RWLockImpl<bIsWriteRecursionAllowed>::GetCondition()
{
#if !defined(AURWLOCK_NO_SIZE_OPTIMIZED_CONDVAR)
return *(ConditionVariableImpl *)this->conditionVariable_;
return *(ConditionVariableInternal *)this->conditionVariable_;
#else
return this->condition_;
#endif
}
template<bool bIsWriteRecursionAllowed>
ConditionVariableImpl &RWLockImpl<bIsWriteRecursionAllowed>::GetConditionWriter()
ConditionVariableInternal &RWLockImpl<bIsWriteRecursionAllowed>::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;

View File

@ -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<true, RWLockImpl> read_;
RWLockAccessView<false, RWLockImpl> 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] {};

View File

@ -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);
}
}

View File

@ -31,7 +31,7 @@ namespace Aurora::Threading::Primitives
private:
AuUInt32 dwState_ {};
ConditionMutexImpl mutex;
ConditionVariableImpl var;
ConditionMutexInternal mutex;
ConditionVariableInternal var;
};
}