From 673d7e328485cdc1a9fa43a97d493ff3a52993f5 Mon Sep 17 00:00:00 2001 From: Jamie Reece Wilson Date: Fri, 13 Dec 2024 21:17:17 +0000 Subject: [PATCH] [+] AuThreadPrimitives::SmallConditionVariable [+] AuSmallCondvar --- Include/Aurora/RuntimeAliases.hpp | 34 +++++++------- .../Primitives/ConditionVariable.hpp | 42 ++++++++++++++--- .../Threading/Primitives/SOOPrimitives.hpp | 11 +++++ .../Primitives/AuConditionVariable.Linux.cpp | 1 + .../Primitives/AuConditionVariable.Linux.hpp | 45 ++++++++++++++++--- .../Primitives/AuConditionVariable.NT.cpp | 1 + .../Primitives/AuConditionVariable.NT.hpp | 44 +++++++++++++++--- 7 files changed, 146 insertions(+), 32 deletions(-) diff --git a/Include/Aurora/RuntimeAliases.hpp b/Include/Aurora/RuntimeAliases.hpp index e760e20a..142ab939 100644 --- a/Include/Aurora/RuntimeAliases.hpp +++ b/Include/Aurora/RuntimeAliases.hpp @@ -69,21 +69,25 @@ using AuByteBuffer = AuMemory::ByteBuffer; using AuSemaphore = AuThreadPrimitives::Semaphore; #endif -using AuRenterableMutex = AuThreadPrimitives::CriticalSection; -using AuCriticalSection = AuThreadPrimitives::CriticalSection; -using AuRWRenterableLock = AuThreadPrimitives::RWRenterableLock; -using AuRWLock = AuThreadPrimitives::RWLock; -using AuCond = AuThreadPrimitives::ConditionVariable; -using AuConditionVariable = AuThreadPrimitives::ConditionVariable; -using AuConditionMutex = AuThreadPrimitives::ConditionMutex; -using AuCondition = AuThreadPrimitives::ConditionVariable; -using AuCondMutex = AuThreadPrimitives::ConditionMutex; -using AuSpinLock = AuThreadPrimitives::SpinLock; -using AuCondEx = AuThreadPrimitives::FlexibleConditionVariable; -using AuFlexibleConditionVariable = AuThreadPrimitives::FlexibleConditionVariable; -using AuConditionEx = AuThreadPrimitives::FlexibleConditionVariable; -using AuBinarySemaphore = AuThreadPrimitives::Event; -using AuEvent = AuThreadPrimitives::Event; +using AuRenterableMutex = AuThreadPrimitives::CriticalSection; +using AuCriticalSection = AuThreadPrimitives::CriticalSection; +using AuRWRenterableLock = AuThreadPrimitives::RWRenterableLock; +using AuRWLock = AuThreadPrimitives::RWLock; +using AuCond = AuThreadPrimitives::ConditionVariable; +using AuConditionVariable = AuThreadPrimitives::ConditionVariable; +using AuSmallConditionVariable = AuThreadPrimitives::SmallConditionVariable; +using AuConditionMutex = AuThreadPrimitives::ConditionMutex; +using AuCondition = AuThreadPrimitives::ConditionVariable; +using AuSmallCondition = AuThreadPrimitives::SmallConditionVariable; +using AuSmallCondVar = AuThreadPrimitives::SmallConditionVariable; +using AuCondVar = AuThreadPrimitives::ConditionVariable; +using AuCondMutex = AuThreadPrimitives::ConditionMutex; +using AuSpinLock = AuThreadPrimitives::SpinLock; +using AuCondEx = AuThreadPrimitives::FlexibleConditionVariable; +using AuFlexibleConditionVariable = AuThreadPrimitives::FlexibleConditionVariable; +using AuConditionEx = AuThreadPrimitives::FlexibleConditionVariable; +using AuBinarySemaphore = AuThreadPrimitives::Event; +using AuEvent = AuThreadPrimitives::Event; using AuFutexMutex = AuThreading::Futexes::FutexWaitable; using AuFutexMutexSpecial = AuThreading::Futexes::FutexWaitableNoVTblMovable; diff --git a/Include/Aurora/Threading/Primitives/ConditionVariable.hpp b/Include/Aurora/Threading/Primitives/ConditionVariable.hpp index 31e029e7..c35ec61e 100644 --- a/Include/Aurora/Threading/Primitives/ConditionVariable.hpp +++ b/Include/Aurora/Threading/Primitives/ConditionVariable.hpp @@ -27,14 +27,14 @@ namespace Aurora::Threading::Primitives * @brief * @param uTimeoutMS timeout in milliseconds or zero for an indefinite amount of time * @return - */ + */ virtual bool WaitForSignal(AuUInt32 uTimeoutMS = 0) = 0; /** * @brief * @param uTimeoutMS timeout in nanoseconds or zero for an indefinite amount of time * @return - */ + */ virtual bool WaitForSignalNS(AuUInt64 uTimeoutNS = 0) = 0; /** @@ -43,13 +43,45 @@ namespace Aurora::Threading::Primitives */ virtual void Broadcast() = 0; + /** + * @brief Schedules a single thread for wake up without guaranteed respect for ordering. + */ + virtual void Signal() = 0; + }; + + AUKN_SHARED_SOO2_NCM(ConditionVariable, IConditionVariable, kPrimitiveSizeCond, + ((const AuSPtr&, pMutex)), + const AuSPtr &pMutex); + + struct ISmallConditionVariable + { + /** + * @brief + * @param uTimeoutMS timeout in milliseconds or zero for an indefinite amount of time + * @return + */ + virtual bool WaitForSignal(IConditionMutex *pMutex, + AuUInt32 uTimeoutMS = 0) = 0; + + /** + * @brief + * @param uTimeoutMS timeout in nanoseconds or zero for an indefinite amount of time + * @return + */ + virtual bool WaitForSignalNS(IConditionMutex *pMutex, + AuUInt64 uTimeoutNS = 0) = 0; + + /** + * @brief Wakes the count of currently sleeping threads without guaranteed respect for ordering. + * Assuming correctness of your mutex paths, this will wake all threads up-to your everyone-be-alert condition. + */ + virtual void Broadcast() = 0; + /** * @brief Schedules a single thread for wake up without guaranteed respect for ordering. */ virtual void Signal() = 0; }; - AUKN_SHARED_SOO2_NCM(ConditionVariable, IConditionVariable, kPrimitiveSizeCond, - ((const AuSPtr&, pMutex)), - const AuSPtr &pMutex); + AUKN_SHARED_SOO2_NCM(SmallConditionVariable, ISmallConditionVariable, kPrimitiveSizeCond2, ()); } \ No newline at end of file diff --git a/Include/Aurora/Threading/Primitives/SOOPrimitives.hpp b/Include/Aurora/Threading/Primitives/SOOPrimitives.hpp index 08a585d4..82d04187 100644 --- a/Include/Aurora/Threading/Primitives/SOOPrimitives.hpp +++ b/Include/Aurora/Threading/Primitives/SOOPrimitives.hpp @@ -25,6 +25,7 @@ namespace Aurora::Threading::Primitives static const auto kPrimitiveSize64NTEvent = 24; static const auto kPrimitiveSize64NTRWLock = 56; static const auto kPrimitiveSize64NTCond = 32; + static const auto kPrimitiveSize64NTCond2 = 16; static const auto kPrimitiveSize64NTCondMutex = 16; static const auto kPrimitiveSize32NTMutex = 8; @@ -33,6 +34,7 @@ namespace Aurora::Threading::Primitives static const auto kPrimitiveSize32NTEvent = 20; static const auto kPrimitiveSize32NTRWLock = 44; static const auto kPrimitiveSize32NTCond = 20; + static const auto kPrimitiveSize32NTCond2 = 12; static const auto kPrimitiveSize32NTCondMutex = 8; static const auto kPrimitiveSize64LinuxMutex = 16; @@ -41,6 +43,7 @@ namespace Aurora::Threading::Primitives static const auto kPrimitiveSize64LinuxEvent = 32; static const auto kPrimitiveSize64LinuxRWLock = 48; static const auto kPrimitiveSize64LinuxCond = 32; + static const auto kPrimitiveSize64LinuxCond2 = 16; static const auto kPrimitiveSize64LinuxCondMutex = 16; // TODO: These values aren't quite correct yet: @@ -50,6 +53,7 @@ namespace Aurora::Threading::Primitives static const auto kPrimitiveSize32LinuxEvent = 32; static const auto kPrimitiveSize32LinuxRWLock = 48; static const auto kPrimitiveSize32LinuxCond = 32; + static const auto kPrimitiveSize32LinuxCond2 = 16; static const auto kPrimitiveSize32LinuxCondMutex = 12; // TODO: Other platforms... @@ -69,6 +73,7 @@ namespace Aurora::Threading::Primitives static const auto kPrimitiveSize64Event = kPrimitiveSize64NTEvent; static const auto kPrimitiveSize64RWLock = kPrimitiveSize64NTRWLock; static const auto kPrimitiveSize64Cond = kPrimitiveSize64NTCond; + static const auto kPrimitiveSize64Cond2 = kPrimitiveSize64NTCond2; static const auto kPrimitiveSize64CondMutex = kPrimitiveSize64NTCondMutex; static const auto kPrimitiveSize32Mutex = kPrimitiveSize32NTMutex; @@ -77,6 +82,7 @@ namespace Aurora::Threading::Primitives static const auto kPrimitiveSize32Event = kPrimitiveSize32NTEvent; static const auto kPrimitiveSize32RWLock = kPrimitiveSize32NTRWLock; static const auto kPrimitiveSize32Cond = kPrimitiveSize32NTCond; + static const auto kPrimitiveSize32Cond2 = kPrimitiveSize32NTCond2; static const auto kPrimitiveSize32CondMutex = kPrimitiveSize32NTCondMutex; #define AURT_ENABLE_HYPER_MUTEX @@ -89,6 +95,7 @@ namespace Aurora::Threading::Primitives static const auto kPrimitiveSize64Event = kPrimitiveSize64LinuxEvent; static const auto kPrimitiveSize64RWLock = kPrimitiveSize64LinuxRWLock; static const auto kPrimitiveSize64Cond = kPrimitiveSize64LinuxCond; + static const auto kPrimitiveSize64Cond2 = kPrimitiveSize64LinuxCond2; static const auto kPrimitiveSize64CondMutex = kPrimitiveSize64LinuxCondMutex; static const auto kPrimitiveSize32Mutex = kPrimitiveSize32LinuxMutex; @@ -97,6 +104,7 @@ namespace Aurora::Threading::Primitives static const auto kPrimitiveSize32Event = kPrimitiveSize32LinuxEvent; static const auto kPrimitiveSize32RWLock = kPrimitiveSize32LinuxRWLock; static const auto kPrimitiveSize32Cond = kPrimitiveSize32LinuxCond; + static const auto kPrimitiveSize32Cond2 = kPrimitiveSize32LinuxCond2; static const auto kPrimitiveSize32CondMutex = kPrimitiveSize32LinuxCondMutex; #define AURT_ENABLE_HYPER_MUTEX @@ -109,6 +117,7 @@ namespace Aurora::Threading::Primitives static const auto kPrimitiveSize64Event = kDefaultPrimitiveSize64; static const auto kPrimitiveSize64RWLock = kDefaultPrimitiveSize64 * 2; static const auto kPrimitiveSize64Cond = kDefaultPrimitiveSize64; + static const auto kPrimitiveSize64Cond2 = kDefaultPrimitiveSize64; static const auto kPrimitiveSize64CondMutex = kDefaultPrimitiveSize64; #endif @@ -121,6 +130,7 @@ namespace Aurora::Threading::Primitives static const auto kPrimitiveSizeEvent = kPrimitiveSize64Event; static const auto kPrimitiveSizeRWLock = kPrimitiveSize64RWLock; static const auto kPrimitiveSizeCond = kPrimitiveSize64Cond; + static const auto kPrimitiveSizeCond2 = kPrimitiveSize64Cond2; static const auto kPrimitiveSizeCondMutex = kPrimitiveSize64CondMutex; #else @@ -131,6 +141,7 @@ namespace Aurora::Threading::Primitives static const auto kPrimitiveSizeEvent = kPrimitiveSize32Event; static const auto kPrimitiveSizeRWLock = kPrimitiveSize32RWLock; static const auto kPrimitiveSizeCond = kPrimitiveSize32Cond; + static const auto kPrimitiveSizeCond2 = kPrimitiveSize32Cond2; static const auto kPrimitiveSizeCondMutex = kPrimitiveSize32CondMutex; #endif diff --git a/Source/Threading/Primitives/AuConditionVariable.Linux.cpp b/Source/Threading/Primitives/AuConditionVariable.Linux.cpp index ba67869b..afb1b8e8 100644 --- a/Source/Threading/Primitives/AuConditionVariable.Linux.cpp +++ b/Source/Threading/Primitives/AuConditionVariable.Linux.cpp @@ -215,6 +215,7 @@ namespace Aurora::Threading::Primitives } AUROXTL_INTERFACE_SOO_SRC(ConditionVariable, ConditionVariableImpl, (const AuSPtr &, pMutex)) + AUROXTL_INTERFACE_SOO_SRC(SmallConditionVariable, ConditionVariableImpl2) } #endif \ No newline at end of file diff --git a/Source/Threading/Primitives/AuConditionVariable.Linux.hpp b/Source/Threading/Primitives/AuConditionVariable.Linux.hpp index 2ffff294..890a61e0 100644 --- a/Source/Threading/Primitives/AuConditionVariable.Linux.hpp +++ b/Source/Threading/Primitives/AuConditionVariable.Linux.hpp @@ -45,37 +45,70 @@ namespace Aurora::Threading::Primitives auline AuSPtr GetMutex() override { - return mutex; + return this->mutex; } auline bool WaitForSignal(AuUInt32 timeout) override { - return cond.WaitForSignalNsEx(&std::static_pointer_cast(this->mutex)->mutex, AuMSToNS(timeout)); + return this->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); + return this->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); + return this->cond.WaitForSignalNsEx(pMutex.get(), timeout); } auline void Signal() override { - cond.Signal(); + this->cond.Signal(); } auline void Broadcast() override { - cond.Broadcast(); + this->cond.Broadcast(); } ConditionVariableInternal cond; std::shared_ptr mutex; }; + + struct ConditionVariableImpl2 final : ISmallConditionVariable + { + auline bool WaitForSignal(IConditionMutex *pMutex, + AuUInt32 timeout) override + { + return this->cond.WaitForSignalNsEx(&AuStaticCast(pMutex)->mutex, AuMSToNS(timeout)); + } + + auline bool WaitForSignalNS(IConditionMutex *pMutex, + AuUInt64 qwTimeout) override + { + return this->cond.WaitForSignalNsEx(&AuStaticCast(pMutex)->mutex, qwTimeout); + } + + inline bool WaitForSignalNsEx(const std::shared_ptr &pMutex, AuUInt64 timeout) + { + return this->cond.WaitForSignalNsEx(pMutex.get(), timeout); + } + + auline void Signal() override + { + this->cond.Signal(); + } + + auline void Broadcast() override + { + this->cond.Broadcast(); + } + + ConditionVariableInternal cond; + }; + static const auto kSizeOfDummyCondVar = sizeof(ConditionVariableInternal); diff --git a/Source/Threading/Primitives/AuConditionVariable.NT.cpp b/Source/Threading/Primitives/AuConditionVariable.NT.cpp index 652886b9..d60b0f3f 100644 --- a/Source/Threading/Primitives/AuConditionVariable.NT.cpp +++ b/Source/Threading/Primitives/AuConditionVariable.NT.cpp @@ -545,6 +545,7 @@ namespace Aurora::Threading::Primitives } AUROXTL_INTERFACE_SOO_SRC(ConditionVariable, ConditionVariableImpl, (const AuSPtr &, pMutex)) + AUROXTL_INTERFACE_SOO_SRC(SmallConditionVariable, ConditionVariableImpl2) } #endif \ No newline at end of file diff --git a/Source/Threading/Primitives/AuConditionVariable.NT.hpp b/Source/Threading/Primitives/AuConditionVariable.NT.hpp index ae9c38ff..f512851a 100644 --- a/Source/Threading/Primitives/AuConditionVariable.NT.hpp +++ b/Source/Threading/Primitives/AuConditionVariable.NT.hpp @@ -46,38 +46,70 @@ namespace Aurora::Threading::Primitives auline AuSPtr GetMutex() override { - return mutex; + return this->mutex; } auline bool WaitForSignal(AuUInt32 timeout) override { - return cond.WaitForSignalNsEx(&std::static_pointer_cast(this->mutex)->mutex, AuMSToNS(timeout)); + return this->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); + return this->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); + return this->cond.WaitForSignalNsEx(pMutex.get(), timeout); } auline void Signal() override { - cond.Signal(); + this->cond.Signal(); } auline void Broadcast() override { - cond.Broadcast(); + this->cond.Broadcast(); } ConditionVariableNT cond; std::shared_ptr mutex; }; + struct ConditionVariableImpl2 final : ISmallConditionVariable + { + auline bool WaitForSignal(IConditionMutex *pMutex, + AuUInt32 timeout) override + { + return this->cond.WaitForSignalNsEx(&AuStaticCast(pMutex)->mutex, AuMSToNS(timeout)); + } + + auline bool WaitForSignalNS(IConditionMutex *pMutex, + AuUInt64 qwTimeout) override + { + return this->cond.WaitForSignalNsEx(&AuStaticCast(pMutex)->mutex, qwTimeout); + } + + inline bool WaitForSignalNsEx(const std::shared_ptr &pMutex, AuUInt64 timeout) + { + return this->cond.WaitForSignalNsEx(pMutex.get(), timeout); + } + + auline void Signal() override + { + this->cond.Signal(); + } + + auline void Broadcast() override + { + this->cond.Broadcast(); + } + + ConditionVariableNT cond; + }; + static const auto kSizeOfDummyCondVar = sizeof(ConditionVariableInternal); static const auto kBoolRequiredLateSet = true;