2021-06-27 21:33:58 +00:00
|
|
|
/***
|
|
|
|
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
|
|
|
|
File: WorkItem.cpp
|
|
|
|
Date: 2021-6-26
|
|
|
|
Author: Reece
|
|
|
|
***/
|
2021-09-30 14:57:41 +00:00
|
|
|
#include <Source/RuntimeInternal.hpp>
|
2021-06-30 09:28:52 +00:00
|
|
|
#include "Async.hpp"
|
2021-06-27 21:25:29 +00:00
|
|
|
#include "WorkItem.hpp"
|
2021-06-30 09:28:52 +00:00
|
|
|
#include "AsyncApp.hpp"
|
2021-06-30 12:00:32 +00:00
|
|
|
#include "Schedular.hpp"
|
2021-06-27 21:25:29 +00:00
|
|
|
|
|
|
|
namespace Aurora::Async
|
|
|
|
{
|
2023-08-10 02:34:44 +00:00
|
|
|
FuncWorker::FuncWorker(IThreadPoolInternal *owner,
|
|
|
|
const WorkerPId_t &worker,
|
|
|
|
AuVoidFunc &&func) :
|
|
|
|
WorkItem(owner, worker, {}),
|
|
|
|
func(func)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-01-23 21:18:58 +00:00
|
|
|
WorkItem::WorkItem(IThreadPoolInternal *owner,
|
|
|
|
const WorkerPId_t &worker,
|
2023-08-10 02:34:44 +00:00
|
|
|
const AuSPtr<IWorkItemHandler> &task) :
|
2023-05-25 00:55:55 +00:00
|
|
|
worker_(worker), task_(task), owner_(owner),
|
|
|
|
finishedEvent_(false, true, true)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
WorkItem::~WorkItem()
|
|
|
|
{
|
2021-06-30 09:28:52 +00:00
|
|
|
//Fail();
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
|
2021-07-07 20:32:59 +00:00
|
|
|
AuSPtr<IWorkItem> WorkItem::WaitFor(const AuSPtr<IWorkItem> &workItem)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2021-06-30 09:41:58 +00:00
|
|
|
bool status {};
|
2021-06-27 21:25:29 +00:00
|
|
|
|
|
|
|
{
|
2022-02-19 11:43:57 +00:00
|
|
|
auto dependency = AuReinterpretCast<WorkItem>(workItem);
|
2021-06-30 09:41:58 +00:00
|
|
|
|
2021-11-05 17:34:23 +00:00
|
|
|
AU_LOCK_GUARD(this->lock);
|
2021-09-06 10:58:08 +00:00
|
|
|
AU_LOCK_GUARD(dependency->lock);
|
2021-06-30 09:34:01 +00:00
|
|
|
|
|
|
|
if (dependency->HasFailed())
|
|
|
|
{
|
2022-05-17 00:59:19 +00:00
|
|
|
Fail();
|
|
|
|
return AU_SHARED_FROM_THIS;
|
2021-06-30 09:34:01 +00:00
|
|
|
}
|
|
|
|
|
2022-05-16 23:46:25 +00:00
|
|
|
if (!AuTryInsert(dependency->waiters_, AuSharedFromThis()))
|
|
|
|
{
|
2022-05-17 00:59:19 +00:00
|
|
|
Fail();
|
|
|
|
return AU_SHARED_FROM_THIS;
|
2022-05-16 23:46:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!AuTryInsert(this->waitOn_, workItem))
|
|
|
|
{
|
|
|
|
AuTryRemove(dependency->waiters_, AuSharedFromThis());
|
2022-05-17 00:59:19 +00:00
|
|
|
Fail();
|
|
|
|
return AU_SHARED_FROM_THIS;
|
2022-05-16 23:46:25 +00:00
|
|
|
}
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
2021-06-30 09:41:58 +00:00
|
|
|
|
2021-07-07 20:32:59 +00:00
|
|
|
return AU_SHARED_FROM_THIS;
|
2021-06-30 09:41:58 +00:00
|
|
|
}
|
2021-07-12 14:37:05 +00:00
|
|
|
|
2022-05-16 23:41:27 +00:00
|
|
|
bool WorkItem::WaitForLocked(const AuList<AuSPtr<IWorkItem>> &workItems)
|
2021-06-30 09:41:58 +00:00
|
|
|
{
|
2022-05-16 23:41:27 +00:00
|
|
|
for (auto &workItem : workItems)
|
2021-06-30 09:41:58 +00:00
|
|
|
{
|
2023-05-02 10:27:06 +00:00
|
|
|
if (!workItem)
|
|
|
|
{
|
|
|
|
SysPushErrorArg();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-05-16 23:41:27 +00:00
|
|
|
auto dependency = AuReinterpretCast<WorkItem>(workItem);
|
|
|
|
AU_LOCK_GUARD(dependency->lock);
|
2021-06-30 09:41:58 +00:00
|
|
|
|
2022-05-16 23:41:27 +00:00
|
|
|
if (dependency->HasFailed())
|
2021-06-30 09:41:58 +00:00
|
|
|
{
|
2022-05-16 23:41:27 +00:00
|
|
|
return false;
|
|
|
|
}
|
2021-06-30 09:41:58 +00:00
|
|
|
|
2022-05-16 23:41:27 +00:00
|
|
|
if (!AuTryInsert(dependency->waiters_, AuSharedFromThis()))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2021-06-30 09:41:58 +00:00
|
|
|
|
2022-05-16 23:41:27 +00:00
|
|
|
if (!AuTryInsert(this->waitOn_, workItem))
|
|
|
|
{
|
|
|
|
AuTryRemove(dependency->waiters_, AuSharedFromThis());
|
|
|
|
return false;
|
2021-06-30 09:41:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-16 23:41:27 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
AuSPtr<IWorkItem> WorkItem::WaitFor(const AuList<AuSPtr<IWorkItem>> &workItems)
|
|
|
|
{
|
|
|
|
bool status {};
|
|
|
|
|
|
|
|
{
|
|
|
|
AU_LOCK_GUARD(this->lock);
|
|
|
|
status = WaitForLocked(workItems);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!status)
|
2021-06-30 09:41:58 +00:00
|
|
|
{
|
|
|
|
Fail();
|
|
|
|
}
|
2021-07-07 20:32:59 +00:00
|
|
|
|
|
|
|
return AU_SHARED_FROM_THIS;
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
2021-07-12 14:37:05 +00:00
|
|
|
|
|
|
|
AuSPtr<IWorkItem> WorkItem::Then(const AuSPtr<IWorkItem> &next)
|
|
|
|
{
|
|
|
|
auto that = AU_SHARED_FROM_THIS;
|
2023-05-02 10:27:06 +00:00
|
|
|
if (!next)
|
|
|
|
{
|
|
|
|
SysPushErrorArg();
|
|
|
|
return {};
|
|
|
|
}
|
2021-07-12 14:37:05 +00:00
|
|
|
next->WaitFor(that);
|
|
|
|
next->Dispatch();
|
|
|
|
return that;
|
|
|
|
}
|
2021-06-30 12:00:32 +00:00
|
|
|
|
2021-07-07 20:32:59 +00:00
|
|
|
AuSPtr<IWorkItem> WorkItem::SetSchedTimeNs(AuUInt64 ns)
|
2021-06-30 12:00:32 +00:00
|
|
|
{
|
2023-08-09 02:21:14 +00:00
|
|
|
this->dispatchTimeNs_ = Time::SteadyClockNS() + ns;
|
2021-11-05 17:34:23 +00:00
|
|
|
return AU_SHARED_FROM_THIS;
|
|
|
|
}
|
|
|
|
|
|
|
|
AuSPtr<IWorkItem> WorkItem::SetSchedTimeAbs(AuUInt32 ms)
|
|
|
|
{
|
2023-08-09 02:21:14 +00:00
|
|
|
return this->SetSchedTimeNsAbs(AuMSToNS<AuUInt64>(ms));
|
2021-11-05 17:34:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
AuSPtr<IWorkItem> WorkItem::SetSchedTimeNsAbs(AuUInt64 ns)
|
|
|
|
{
|
2023-08-09 02:21:14 +00:00
|
|
|
auto uNow = AuTime::CurrentClockNS();
|
|
|
|
if (uNow > ns)
|
|
|
|
{
|
|
|
|
return AU_SHARED_FROM_THIS;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->dispatchTimeNs_ = AuTime::SteadyClockNS() + (ns - uNow);
|
|
|
|
return AU_SHARED_FROM_THIS;
|
|
|
|
}
|
|
|
|
|
|
|
|
AuSPtr<IWorkItem> WorkItem::SetSchedSteadyTimeNsAbs(AuUInt64 ns)
|
|
|
|
{
|
|
|
|
this->dispatchTimeNs_ = ns;
|
2021-07-07 20:32:59 +00:00
|
|
|
return AU_SHARED_FROM_THIS;
|
2021-06-30 12:00:32 +00:00
|
|
|
}
|
|
|
|
|
2021-07-07 20:32:59 +00:00
|
|
|
AuSPtr<IWorkItem> WorkItem::SetSchedTime(AuUInt32 ms)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2023-08-09 02:21:14 +00:00
|
|
|
this->dispatchTimeNs_ = Time::SteadyClockNS() + AuMSToNS<AuUInt64>(ms);
|
2021-07-07 20:32:59 +00:00
|
|
|
return AU_SHARED_FROM_THIS;
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
2021-07-15 16:16:23 +00:00
|
|
|
|
|
|
|
AuSPtr<IWorkItem> WorkItem::AddDelayTime(AuUInt32 ms)
|
|
|
|
{
|
2022-06-12 18:23:18 +00:00
|
|
|
this->delayTimeNs_ += AuMSToNS<AuUInt64>(ms);
|
2021-07-15 16:16:23 +00:00
|
|
|
return AU_SHARED_FROM_THIS;
|
|
|
|
}
|
|
|
|
|
|
|
|
AuSPtr<IWorkItem> WorkItem::AddDelayTimeNs(AuUInt64 ns)
|
|
|
|
{
|
2021-11-05 17:34:23 +00:00
|
|
|
this->delayTimeNs_ += ns;
|
2021-07-15 16:16:23 +00:00
|
|
|
return AU_SHARED_FROM_THIS;
|
|
|
|
}
|
2021-06-27 21:25:29 +00:00
|
|
|
|
2021-07-07 20:32:59 +00:00
|
|
|
AuSPtr<IWorkItem> WorkItem::Dispatch()
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
|
|
|
DispatchEx(false);
|
2021-07-07 20:32:59 +00:00
|
|
|
return AU_SHARED_FROM_THIS;
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WorkItem::DispatchEx(bool check)
|
|
|
|
{
|
2023-02-08 18:23:37 +00:00
|
|
|
AU_LOCK_GUARD(this->lock);
|
2021-06-27 21:25:29 +00:00
|
|
|
|
2022-05-16 23:41:27 +00:00
|
|
|
DispatchExLocked(check);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WorkItem::DispatchExLocked(bool check)
|
|
|
|
{
|
2021-06-27 21:25:29 +00:00
|
|
|
if (check)
|
|
|
|
{
|
2021-11-05 17:34:23 +00:00
|
|
|
if (this->dispatchPending_)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-30 09:34:01 +00:00
|
|
|
if (HasFailed())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-06-27 21:25:29 +00:00
|
|
|
for (auto itr = waitOn_.begin(); itr != waitOn_.end(); )
|
|
|
|
{
|
|
|
|
auto &waitable = *itr;
|
|
|
|
|
|
|
|
if (!waitable->HasFinished())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
itr = waitOn_.erase(itr);
|
|
|
|
}
|
|
|
|
|
2021-11-05 17:34:23 +00:00
|
|
|
this->dispatchPending_ = true;
|
2021-09-06 10:58:08 +00:00
|
|
|
|
2023-08-09 02:21:14 +00:00
|
|
|
if (Time::SteadyClockNS() < this->dispatchTimeNs_)
|
2021-07-15 16:16:23 +00:00
|
|
|
{
|
2022-08-13 21:59:44 +00:00
|
|
|
if (!Schedule())
|
|
|
|
{
|
|
|
|
this->Fail();
|
|
|
|
}
|
2021-07-15 16:16:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-01-19 17:08:13 +00:00
|
|
|
if (auto delay = AuExchange(delayTimeNs_, {}))
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2023-08-09 02:21:14 +00:00
|
|
|
this->dispatchTimeNs_ = delay + Time::SteadyClockNS();
|
2022-08-13 21:59:44 +00:00
|
|
|
if (!Schedule())
|
|
|
|
{
|
|
|
|
this->Fail();
|
|
|
|
}
|
2021-06-27 21:25:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendOff();
|
|
|
|
}
|
|
|
|
|
2023-05-25 00:55:55 +00:00
|
|
|
EWorkPrio WorkItem::GetPrio()
|
2021-11-05 17:34:23 +00:00
|
|
|
{
|
2023-05-25 00:55:55 +00:00
|
|
|
return this->prio_;
|
2021-11-05 17:34:23 +00:00
|
|
|
}
|
|
|
|
|
2023-05-25 00:55:55 +00:00
|
|
|
void WorkItem::SetPrio(EWorkPrio prio)
|
2021-11-05 17:34:23 +00:00
|
|
|
{
|
2023-05-25 00:55:55 +00:00
|
|
|
this->prio_ = prio;
|
2021-11-05 17:34:23 +00:00
|
|
|
}
|
|
|
|
|
2021-06-30 09:28:52 +00:00
|
|
|
void WorkItem::CancelAsync()
|
|
|
|
{
|
2023-02-08 18:23:37 +00:00
|
|
|
AU_TRY_LOCK_GUARD_NAMED(this->lock2, asd);
|
2021-06-30 09:28:52 +00:00
|
|
|
Fail();
|
|
|
|
}
|
|
|
|
|
2023-08-10 02:34:44 +00:00
|
|
|
void WorkItem::DispatchTask(IWorkItemHandler::ProcessInfo &info)
|
2023-02-08 18:23:37 +00:00
|
|
|
{
|
|
|
|
if (this->task_)
|
|
|
|
{
|
2023-08-10 02:34:44 +00:00
|
|
|
|
2023-02-08 18:23:37 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
this->task_->DispatchFrame(info);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
// TODO: runtime config for root level exception caught behaviour
|
|
|
|
SysPushErrorCatch();
|
|
|
|
Fail();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2023-08-10 02:34:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WorkItem::RunAsyncLocked2()
|
|
|
|
{
|
|
|
|
AU_LOCK_GUARD(this->lock2);
|
2023-02-08 18:23:37 +00:00
|
|
|
|
2023-08-10 02:34:44 +00:00
|
|
|
IWorkItemHandler::ProcessInfo info(true);
|
|
|
|
info.pool = this->owner_->ToThreadPool();
|
|
|
|
|
|
|
|
DispatchTask(info);
|
|
|
|
|
2023-02-08 18:23:37 +00:00
|
|
|
RunAsyncLocked2(info);
|
|
|
|
}
|
|
|
|
|
2021-06-30 09:28:52 +00:00
|
|
|
void WorkItem::RunAsync()
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2023-02-08 18:23:37 +00:00
|
|
|
AU_LOCK_GUARD(this->lock2);
|
2022-05-17 01:43:26 +00:00
|
|
|
RunAsyncLocked();
|
|
|
|
}
|
|
|
|
|
|
|
|
void WorkItem::RunAsyncLocked()
|
|
|
|
{
|
2021-06-27 21:25:29 +00:00
|
|
|
IWorkItemHandler::ProcessInfo info(true);
|
2021-11-05 17:34:23 +00:00
|
|
|
info.pool = this->owner_->ToThreadPool();
|
2021-09-06 10:58:08 +00:00
|
|
|
|
2021-11-05 17:34:23 +00:00
|
|
|
if (this->task_)
|
2021-09-06 10:58:08 +00:00
|
|
|
{
|
2022-10-14 06:14:56 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
this->task_->DispatchFrame(info);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
// TODO: runtime config for root level exception caught behaviour
|
|
|
|
SysPushErrorCatch();
|
|
|
|
Fail();
|
|
|
|
return;
|
|
|
|
}
|
2021-09-06 10:58:08 +00:00
|
|
|
}
|
2021-06-27 21:25:29 +00:00
|
|
|
|
2023-02-08 18:23:37 +00:00
|
|
|
AU_LOCK_GUARD(this->lock);
|
|
|
|
RunAsyncLocked2(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WorkItem::RunAsyncLocked2(const IWorkItemHandler::ProcessInfo &info)
|
|
|
|
{
|
|
|
|
|
2021-06-27 21:25:29 +00:00
|
|
|
switch (info.type)
|
|
|
|
{
|
2022-05-16 23:41:27 +00:00
|
|
|
case ETickType::eFinished:
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2022-05-17 01:43:26 +00:00
|
|
|
|
2021-06-27 21:25:29 +00:00
|
|
|
// do nothing
|
|
|
|
break;
|
|
|
|
}
|
2022-05-16 23:41:27 +00:00
|
|
|
case ETickType::eEnumInvalid:
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
|
|
|
SysPanic("Handle Invalid");
|
|
|
|
break;
|
|
|
|
}
|
2022-05-16 23:41:27 +00:00
|
|
|
case ETickType::eSchedule:
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
|
|
|
if (info.reschedMs)
|
|
|
|
{
|
|
|
|
SetSchedTime(info.reschedMs);
|
2021-11-08 00:11:01 +00:00
|
|
|
}
|
|
|
|
else if (info.reschedNs)
|
2021-06-30 12:00:32 +00:00
|
|
|
{
|
|
|
|
SetSchedTimeNs(info.reschedNs);
|
|
|
|
}
|
2021-11-08 00:11:01 +00:00
|
|
|
else if (info.reschedClockAbsMs)
|
|
|
|
{
|
|
|
|
SetSchedTimeAbs(info.reschedMs);
|
|
|
|
}
|
|
|
|
else if (info.reschedClockAbsNs)
|
|
|
|
{
|
|
|
|
SetSchedTimeNsAbs(info.reschedNs);
|
|
|
|
}
|
2022-05-16 23:41:27 +00:00
|
|
|
|
|
|
|
if (!WaitForLocked(info.waitFor))
|
|
|
|
{
|
|
|
|
Fail();
|
|
|
|
}
|
2021-06-30 09:34:01 +00:00
|
|
|
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
2021-06-30 09:34:01 +00:00
|
|
|
[[fallthrough]];
|
2022-05-16 23:41:27 +00:00
|
|
|
case ETickType::eRerun:
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2022-05-16 23:41:27 +00:00
|
|
|
DispatchExLocked(false);
|
2021-06-27 21:25:29 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-05-16 23:41:27 +00:00
|
|
|
case ETickType::eFailed:
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
|
|
|
Fail();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-05 17:34:23 +00:00
|
|
|
this->finished = true;
|
|
|
|
if (this->finishedEvent_)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2021-11-05 17:34:23 +00:00
|
|
|
this->finishedEvent_->Set();
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
2021-09-06 10:58:08 +00:00
|
|
|
|
2021-11-05 17:34:23 +00:00
|
|
|
for (auto &waiter : this->waiters_)
|
2021-09-06 10:58:08 +00:00
|
|
|
{
|
2023-02-08 18:23:37 +00:00
|
|
|
AuReinterpretCast<WorkItem>(waiter)->DispatchExLocked(true);
|
2021-09-06 10:58:08 +00:00
|
|
|
}
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WorkItem::Fail()
|
|
|
|
{
|
|
|
|
failed = true;
|
|
|
|
|
2022-01-19 17:08:13 +00:00
|
|
|
if (auto task_ = AuExchange(this->task_, {}))
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2022-05-16 23:41:27 +00:00
|
|
|
task_->OnFailure();
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
|
2021-11-05 17:34:23 +00:00
|
|
|
for (auto &waiter : this->waiters_)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2022-02-19 11:50:14 +00:00
|
|
|
AuReinterpretCast<WorkItem>(waiter)->Fail();
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
|
2021-11-05 17:34:23 +00:00
|
|
|
this->waiters_.clear();
|
|
|
|
this->waitOn_.clear();
|
2021-06-27 21:25:29 +00:00
|
|
|
|
2021-11-05 17:34:23 +00:00
|
|
|
if (this->finishedEvent_)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2021-11-05 17:34:23 +00:00
|
|
|
this->finishedEvent_->Set();
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WorkItem::BlockUntilComplete()
|
|
|
|
{
|
2021-11-05 17:34:23 +00:00
|
|
|
if (!this->finishedEvent_) return false;
|
2023-05-25 00:55:55 +00:00
|
|
|
return this->owner_->WaitFor(this->worker_, AuUnsafeRaiiToShared(this->finishedEvent_.AsPointer()), 0);
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool WorkItem::HasFinished()
|
|
|
|
{
|
2021-11-05 17:34:23 +00:00
|
|
|
return this->finished;
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
|
2021-09-29 08:01:42 +00:00
|
|
|
void WorkItem::Cancel()
|
|
|
|
{
|
2023-02-08 18:23:37 +00:00
|
|
|
AU_LOCK_GUARD(this->lock2);
|
2021-09-29 08:01:42 +00:00
|
|
|
Fail();
|
|
|
|
}
|
|
|
|
|
2021-06-27 21:25:29 +00:00
|
|
|
bool WorkItem::HasFailed()
|
|
|
|
{
|
2021-11-05 17:34:23 +00:00
|
|
|
return this->failed;
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
|
2022-08-13 21:59:44 +00:00
|
|
|
bool WorkItem::Schedule()
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2022-08-13 21:59:44 +00:00
|
|
|
return Async::Schedule(this->dispatchTimeNs_, this->owner_, this->worker_, AuSharedFromThis());
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WorkItem::SendOff()
|
|
|
|
{
|
2021-11-05 17:34:23 +00:00
|
|
|
if (!this->task_)
|
2021-10-06 13:48:28 +00:00
|
|
|
{
|
|
|
|
// If we aren't actually calling a task interface, we may as well just dispatch objects waiting on us from here
|
2023-02-08 18:23:37 +00:00
|
|
|
RunAsyncLocked2();
|
2021-10-06 13:48:28 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-05-17 01:43:26 +00:00
|
|
|
this->owner_->Run(this->worker_, AuSharedFromThis());
|
2021-10-06 13:48:28 +00:00
|
|
|
}
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
2021-11-05 17:34:23 +00:00
|
|
|
static auto GetWorkerInternal()
|
|
|
|
{
|
|
|
|
return static_cast<AsyncApp *>(GetAsyncApp());
|
|
|
|
}
|
2021-06-27 21:25:29 +00:00
|
|
|
|
2022-05-17 01:43:26 +00:00
|
|
|
inline auto GetWorkerInternal(const AuSPtr<IThreadPool> &pool)
|
|
|
|
{
|
|
|
|
if (pool.get() == AuStaticCast<IAsyncApp>(gAsyncApp))
|
|
|
|
{
|
|
|
|
return AuUnsafeRaiiToShared(AuStaticCast<ThreadPool>(gAsyncApp));
|
|
|
|
}
|
|
|
|
|
|
|
|
return AuStaticPointerCast<ThreadPool>(pool);
|
|
|
|
}
|
|
|
|
|
2023-08-10 02:34:44 +00:00
|
|
|
void FuncWorker::DispatchTask(IWorkItemHandler::ProcessInfo &info)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2023-08-10 02:34:44 +00:00
|
|
|
if (func)
|
|
|
|
{
|
|
|
|
func();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AUKN_SYM AuSPtr<IWorkItem> NewWorkItem(const WorkerId_t &worker, const AuSPtr<IWorkItemHandler> &task)
|
|
|
|
{
|
|
|
|
AU_DEBUG_MEMCRUNCH;
|
|
|
|
|
2021-10-06 13:48:28 +00:00
|
|
|
if (!task)
|
|
|
|
{
|
2022-06-22 13:42:17 +00:00
|
|
|
SysPushErrorArg("WorkItem has null task. Running out of memory?");
|
2021-10-06 13:48:28 +00:00
|
|
|
return {};
|
|
|
|
}
|
2021-11-05 17:34:23 +00:00
|
|
|
|
2023-08-10 02:34:44 +00:00
|
|
|
return AuMakeShared<WorkItem>(GetWorkerInternal(), WorkerPId_t { AuAsync::GetCurrentWorkerPId().pool, worker }, task);
|
2021-11-05 17:34:23 +00:00
|
|
|
}
|
|
|
|
|
2023-08-10 02:34:44 +00:00
|
|
|
AUKN_SYM AuSPtr<IWorkItem> NewWorkFunction(const WorkerPId_t &worker, AuVoidFunc func)
|
2021-11-05 17:34:23 +00:00
|
|
|
{
|
2023-08-10 02:34:44 +00:00
|
|
|
AU_DEBUG_MEMCRUNCH;
|
|
|
|
|
|
|
|
if (!func)
|
|
|
|
{
|
|
|
|
SysPushErrorArg("WorkItem has null function");
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!worker)
|
|
|
|
{
|
|
|
|
SysPushErrorArg("invalid worker");
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
return AuMakeSharedThrow<FuncWorker>(GetWorkerInternal(worker.pool).get(), worker, AuMove(func));
|
|
|
|
}
|
|
|
|
|
|
|
|
AUKN_SYM AuSPtr<IWorkItem> NewWorkItem(const WorkerPId_t &worker, const AuSPtr<IWorkItemHandler> &task)
|
|
|
|
{
|
|
|
|
AU_DEBUG_MEMCRUNCH;
|
|
|
|
|
2021-11-05 17:34:23 +00:00
|
|
|
if (!task)
|
|
|
|
{
|
2022-06-22 13:42:17 +00:00
|
|
|
SysPushErrorArg("WorkItem has null task. Running out of memory?");
|
2021-11-05 17:34:23 +00:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2023-08-10 02:34:44 +00:00
|
|
|
if (!worker)
|
2021-11-05 17:34:23 +00:00
|
|
|
{
|
2023-08-10 02:34:44 +00:00
|
|
|
SysPushErrorArg("invalid worker");
|
2021-11-05 17:34:23 +00:00
|
|
|
return {};
|
|
|
|
}
|
2022-05-17 01:43:26 +00:00
|
|
|
|
2023-08-10 02:34:44 +00:00
|
|
|
return AuMakeSharedThrow<WorkItem>(GetWorkerInternal(worker.pool).get(), worker, task);
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
2021-10-06 13:48:28 +00:00
|
|
|
|
|
|
|
AUKN_SYM AuSPtr<IWorkItem> NewFence()
|
|
|
|
{
|
2023-08-10 02:34:44 +00:00
|
|
|
return AuMakeShared<WorkItem>(GetWorkerInternal(), AuAsync::GetCurrentWorkerPId(), AuSPtr<IWorkItemHandler>{});
|
2021-10-06 13:48:28 +00:00
|
|
|
}
|
2021-09-29 10:47:54 +00:00
|
|
|
|
|
|
|
void *WorkItem::GetPrivateData()
|
|
|
|
{
|
|
|
|
if (!this->task_)
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this->task_->GetPrivateData();
|
|
|
|
}
|
|
|
|
|
|
|
|
AuOptional<void *> WorkItem::ToWorkResultT()
|
|
|
|
{
|
|
|
|
if (!this->task_)
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto priv = reinterpret_cast<Async::WorkPriv *>(this->task_->GetPrivateData());
|
|
|
|
if (!priv)
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->magic == AuConvertMagicTag32("BWOT"))
|
|
|
|
{
|
|
|
|
|
|
|
|
return reinterpret_cast<Async::BasicWorkCtx *>(priv)->opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {};
|
|
|
|
}
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|