/*** Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuWakeOnAddress.hpp Date: 2023-3-10 Author: Reece ***/ #pragma once #include "Primitives/AuConditionMutex.Generic.hpp" #include "Primitives/AuConditionVariable.Generic.hpp" namespace Aurora::Threading { static const auto kDefaultWaitPerProcess = 64; struct WaitState; struct WaitBuffer { char buffer[8]; AuUInt8 uSize; static WaitBuffer From(const void *pBuf, AuUInt8 uSize); bool Compare(const void *pBuf); bool Compare(WaitState &state); }; struct WaitState { WaitBuffer compare; //AuOptionalEx qwNanoseconds; AuOptionalEx qwNanosecondsAbs; AuOptionalEx uDownsizeMask; AuUInt32 uWordSize {}; }; struct WaitEntry { WaitEntry(); ~WaitEntry(); WaitEntry *pNext {}; WaitEntry *pBefore {}; // 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 // state const void *pAddress {}; AuUInt8 uSize {}; // bookkeeping (parent container) bool bOverflow {}; bool bReleaseOnWake {}; bool TryAcquire(const void *pAddress, AuUInt8 uSize); void Release(); bool SleepOn(WaitState &state); bool TryWake(const void *pAddress); bool TryWakeNoLock(const void *pAddress); bool TryWakeNoLockNoReallyNoLock(const void *pAddress); }; struct ProcessListWait { WaitEntry *pHead {}; WaitEntry *pTail {}; }; struct ProcessWaitNodeContainer { AuUInt32 uAtomic {}; #if defined(WOA_ENABLE_OLD_SHORT_LIST) WaitEntry entries[kDefaultWaitPerProcess]; #endif ProcessListWait waitList; WaitEntry *WaitBufferFrom(const void *pAddress, AuUInt8 uSize); template bool IterateWake(T callback); void Lock(); void Unlock(); }; struct ProcessWaitContainer { ProcessWaitNodeContainer list[kDefaultWaitPerProcess]; WaitEntry *WaitBufferFrom(const void *pAddress, AuUInt8 uSize); template bool IterateWake(const void *pAddress, T callback); }; }