[*] Refactor WorkItemHandler EProcessNext -> ETickType

[*] AuAsync aue 1 regression
This commit is contained in:
Reece Wilson 2022-05-17 00:41:27 +01:00
parent 24fc2fd90d
commit 286ae14a7b
5 changed files with 73 additions and 47 deletions

View File

@ -9,25 +9,24 @@
namespace Aurora::Async
{
AUE_DEFINE(ETickType,
(
eFinished,
eRerun,
eSchedule,
eFailed
));
struct IWorkItemHandler
{
enum class EProcessNext
{
eInvalid = -1,
eFinished = 0,
eRerun,
eSchedule,
eFailed
};
struct ProcessInfo
{
ProcessInfo(bool finished) : type(finished ? EProcessNext::eFinished : EProcessNext::eFailed) {}
ProcessInfo(EProcessNext type) : type(type) {}
ProcessInfo(const AuList<AuSPtr<IWorkItem>> &blockedBy) : type(EProcessNext::eSchedule), waitFor(blockedBy) {}
ProcessInfo(bool finished) : type(finished ? ETickType::eFinished : ETickType::eFailed) {}
ProcessInfo(ETickType type) : type(type) {}
ProcessInfo(const AuList<AuSPtr<IWorkItem>> &blockedBy) : type(ETickType::eSchedule), waitFor(blockedBy) {}
// ...
EProcessNext type;
ETickType type;
AuList<AuSPtr<IWorkItem>> waitFor;
AuUInt32 reschedMs {};
AuUInt64 reschedNs {};
@ -40,9 +39,8 @@ namespace Aurora::Async
virtual void DispatchFrame(ProcessInfo &info) = 0;
/// A really terrible name for the overloadable method that serves as the critical failure callback
/// You have a 'shutdown'/free function you can overload, it's called the dtor
/// Don't moan about the shitty naming of this, im not refactoring it
virtual void Shutdown() = 0;
/// This may run from any thread
virtual void OnFailure() {};
virtual void *GetPrivateData() { return nullptr; }
};

View File

@ -22,7 +22,7 @@ namespace Aurora::Async
private:
#if !defined(_CPPSHARP)
void DispatchFrame(ProcessInfo &info) override
inline void DispatchFrame(ProcessInfo &info) override
{
try
{
@ -34,7 +34,7 @@ namespace Aurora::Async
}
}
void Shutdown() override
inline void OnFailure() override
{
try
{
@ -66,12 +66,12 @@ namespace Aurora::Async
{
if (!frame)
{
info.type = IWorkItemHandler::EProcessNext::eFinished;
info.type = IWorkItemHandler::ETickType::eFinished;
return;
}
}
frame();
info.type = IWorkItemHandler::EProcessNext::eFinished;
info.type = IWorkItemHandler::ETickType::eFinished;
}
void Shutdown() override

View File

@ -175,7 +175,7 @@ namespace Aurora::Async
}
}
void Shutdown() override
void OnFailure() override
{
AU_LOCK_GUARD(this->lock_);
ShutdownNoLock();

View File

@ -54,29 +54,43 @@ namespace Aurora::Async
return AU_SHARED_FROM_THIS;
}
bool WorkItem::WaitForLocked(const AuList<AuSPtr<IWorkItem>> &workItems)
{
for (auto &workItem : workItems)
{
auto dependency = AuReinterpretCast<WorkItem>(workItem);
AU_LOCK_GUARD(dependency->lock);
if (dependency->HasFailed())
{
return false;
}
if (!AuTryInsert(dependency->waiters_, AuSharedFromThis()))
{
return false;
}
if (!AuTryInsert(this->waitOn_, workItem))
{
AuTryRemove(dependency->waiters_, AuSharedFromThis());
return false;
}
}
return true;
}
AuSPtr<IWorkItem> WorkItem::WaitFor(const AuList<AuSPtr<IWorkItem>> &workItems)
{
bool status {};
{
AU_LOCK_GUARD(this->lock);
for (auto &workItem : workItems)
{
auto dependency = AuReinterpretCast<WorkItem>(workItem);
AU_LOCK_GUARD(dependency->lock);
if (dependency->HasFailed())
{
status = true;
}
dependency->waiters_.push_back(shared_from_this());
this->waitOn_.push_back(workItem);
}
status = WaitForLocked(workItems);
}
if (status)
if (!status)
{
Fail();
}
@ -100,7 +114,7 @@ namespace Aurora::Async
AuSPtr<IWorkItem> WorkItem::SetSchedTimeAbs(AuUInt32 ms)
{
this->dispatchTimeNs_ = AuUInt64(ms) * AuUInt64(1000000);
this->dispatchTimeNs_ = AuUInt64(ms) * AuMSToNS<AuUInt64>(ms);
return AU_SHARED_FROM_THIS;
}
@ -112,13 +126,13 @@ namespace Aurora::Async
AuSPtr<IWorkItem> WorkItem::SetSchedTime(AuUInt32 ms)
{
this->dispatchTimeNs_ = Time::CurrentClockNS() + (AuUInt64(ms) * AuUInt64(1000000));
this->dispatchTimeNs_ = Time::CurrentClockNS() + AuMSToNS<AuUInt64>(ms);
return AU_SHARED_FROM_THIS;
}
AuSPtr<IWorkItem> WorkItem::AddDelayTime(AuUInt32 ms)
{
this->delayTimeNs_ += AuUInt64(ms) * AuUInt64(1000000);
this->delayTimeNs_ += AuUInt64(ms) * AuMSToNS<AuUInt64>(ms);
return AU_SHARED_FROM_THIS;
}
@ -138,6 +152,11 @@ namespace Aurora::Async
{
AU_LOCK_GUARD(lock);
DispatchExLocked(check);
}
void WorkItem::DispatchExLocked(bool check)
{
if (check)
{
if (this->dispatchPending_)
@ -211,17 +230,17 @@ namespace Aurora::Async
switch (info.type)
{
case IWorkItemHandler::EProcessNext::eFinished:
case ETickType::eFinished:
{
// do nothing
break;
}
case IWorkItemHandler::EProcessNext::eInvalid:
case ETickType::eEnumInvalid:
{
SysPanic("Handle Invalid");
break;
}
case IWorkItemHandler::EProcessNext::eSchedule:
case ETickType::eSchedule:
{
if (info.reschedMs)
{
@ -239,16 +258,20 @@ namespace Aurora::Async
{
SetSchedTimeNsAbs(info.reschedNs);
}
WaitFor(info.waitFor);
if (!WaitForLocked(info.waitFor))
{
Fail();
}
}
[[fallthrough]];
case IWorkItemHandler::EProcessNext::eRerun:
case ETickType::eRerun:
{
DispatchEx(false);
DispatchExLocked(false);
return;
}
case IWorkItemHandler::EProcessNext::eFailed:
case ETickType::eFailed:
{
Fail();
return;
@ -273,7 +296,7 @@ namespace Aurora::Async
if (auto task_ = AuExchange(this->task_, {}))
{
task_->Shutdown();
task_->OnFailure();
}
for (auto &waiter : this->waiters_)

View File

@ -46,7 +46,12 @@ namespace Aurora::Async
void SetPrio(float val) override;
private:
bool WaitForLocked(const AuList<AuSPtr<IWorkItem>> &workItem);
void DispatchEx(bool check);
void DispatchExLocked(bool check);
AuSPtr<IWorkItemHandler> task_;
WorkerId_t worker_;
float prio_ = 0.5f;