AuroraRuntime/Source/Threading/AuWakeOnAddress.hpp

91 lines
2.2 KiB
C++

/***
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 = 12;
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<AuUInt64> qwNanoseconds;
AuOptionalEx<AuUInt64> qwNanosecondsAbs;
AuOptionalEx<AuUInt32> 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 ProcessWaitContainer
{
AuUInt32 uAtomic {};
#if defined(WOA_ENABLE_OLD_SHORT_LIST)
WaitEntry entries[kDefaultWaitPerProcess];
#endif
ProcessListWait waitList;
WaitEntry *WaitBufferFrom(void *pAddress, AuUInt8 uSize);
template <typename T>
bool IterateWake(T callback);
void Lock();
void Unlock();
};
}