AuroraRuntime/Source/Async/AuThreadState.cpp

116 lines
2.5 KiB
C++

/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuThreadState.hpp
Date: 2023-11-04
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "Async.hpp"
#include "AuThreadState.hpp"
#include <Source/IO/Loop/LSAsync.hpp>
#include "ThreadWorkerQueueShim.hpp"
namespace Aurora::Async
{
ThreadStateSync::ThreadStateSync():
cvVariable(AuUnsafeRaiiToShared(cvWorkMutex.AsPointer()))
{
}
ThreadStateBase::ThreadStateBase()
{
}
ThreadStateBase::~ThreadStateBase()
{
if (this->asyncLoop)
{
this->asyncLoop->pParent = nullptr;
if (this->asyncLoop)
{
(void)this->asyncLoop->SourceRemove(this->sync.eventLs);
}
}
}
bool ThreadStateSync::Init()
{
this->eventLs = AuLoop::NewLSAsync();
return true;
}
bool ThreadStateBase::Init()
{
if (!(this->asyncLoop = AuMakeShared<AsyncLoop>()))
{
SysPushErrorMemory();
return {};
}
this->asyncLoop->pParent = this;
if (!this->asyncLoop->Init())
{
SysPushErrorNested();
return {};
}
if (!this->sync.Init())
{
SysPushErrorNested();
return {};
}
if (!this->asyncLoop->SourceAdd(this->sync.eventLs))
{
SysPushErrorNested();
return {};
}
return true;
}
void ThreadStateSync::SetEvent(bool bBoth, bool bHasWork)
{
if (bHasWork)
{
AuAtomicAdd(&this->cvHasWork, 1u);
}
if (auto pEvent = this->eventLs)
{
if (AuAtomicTestAndSet(&this->cvLSActive, 0u) == 0)
{
pEvent->Set();
}
}
if (bBoth)
{
this->cvWorkMutex->Lock();
this->cvWorkMutex->Unlock();
this->cvVariable->Signal();
}
}
void ThreadStateSync::UpdateCVState(ThreadState *pState)
{
auto uState = pState->sync.cvHasWork;
auto uMin = AuMin(uState, pState->pendingWorkItems.size());
if (!uMin) uMin = 1;
while (uState &&
AuAtomicCompareExchange<AuUInt32>(&pState->sync.cvHasWork, uState - uMin, uState) != uState)
{
uState = pState->sync.cvHasWork;
if (uState < uMin)
{
uMin = uState;
}
}
}
}