125 lines
2.6 KiB
C++
125 lines
2.6 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 ThreadStateBase::Deinit()
|
|
{
|
|
AuResetMember(this->singletons);
|
|
}
|
|
|
|
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 = AuAtomicLoad(&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;
|
|
}
|
|
}
|
|
}
|
|
} |