[-] Engine 0.0/1.0 async

This commit is contained in:
Reece Wilson 2023-09-22 06:05:39 +01:00
parent 7739652ad3
commit f6437ef66e
16 changed files with 18 additions and 910 deletions

View File

@ -14,9 +14,6 @@
#include "IThreadPool.hpp" #include "IThreadPool.hpp"
#include "IAsyncApp.hpp" #include "IAsyncApp.hpp"
#include "Legacy/Jobs.hpp"
#include "Legacy/Tasks.hpp"
namespace Aurora::Async namespace Aurora::Async
{ {
AUKN_SYM IAsyncApp * GetAsyncApp(); AUKN_SYM IAsyncApp * GetAsyncApp();
@ -59,10 +56,4 @@ namespace Aurora::Async
#if !defined(_CPPSHARP) #if !defined(_CPPSHARP)
#include "IPCPromises.hpp" #include "IPCPromises.hpp"
#include "Legacy/JobFrom.hpp"
#include "Legacy/TaskFrom.hpp"
#include "Legacy/WorkPairImpl.hpp"
#include "Legacy/WorkBasic.hpp"
#include "Legacy/OldTrash.hpp"
#endif #endif

View File

@ -265,11 +265,11 @@ private:
return; return;
} }
AuAsync::NewWorkItem(this->pid.value(), AuMakeSharedPanic<AuAsync::BasicWorkStdFunc>([pThat = this->SharedFromThis()] AuAsync::DispatchOn(this->pid.value(), [pThat = this->SharedFromThis()]
{ {
AU_LOCK_GUARD(pThat->mutex); AU_LOCK_GUARD(pThat->mutex);
pThat->SubmitComplete(); pThat->SubmitComplete();
}))->Dispatch(); });
} }
} }

View File

@ -56,6 +56,5 @@ namespace Aurora::Async
virtual void Cancel() = 0; virtual void Cancel() = 0;
virtual void *GetPrivateData() = 0; virtual void *GetPrivateData() = 0;
virtual AuOptional<void *> ToWorkResultT() = 0;
}; };
} }

View File

@ -1,5 +0,0 @@
> Deprecated APIs <
* Wont remove
* Powering old projects
* Sometimes used as shorthands internally

View File

@ -1,184 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: JobFrom.hpp
Date: 2021-11-1
Author: Reece
***/
#pragma once
namespace Aurora::Async
{
template<class Info_t = AVoid, class Result_t = AVoid, class Callable_t>
static inline FJob<Info_t, Result_t> JobFromPairConsumer(const /*AuConsumer<const Info_t &, const Result_t &> */ Callable_t&onSuccess)
{
FJob<Info_t, Result_t> ret;
ret.onSuccess = [=](const Info_t &in, const Result_t &a)
{
onSuccess(in, a);
};
return ret;
}
template<class Info_t = AVoid, class Result_t = AVoid, class Callable_t>
static inline FJob<Info_t, Result_t> JobFromResultConsumer(/*AuConsumer<const Result_t &> */ Callable_t onSuccess)
{
FJob<Info_t, Result_t> ret;
ret.onSuccess = [=](const Info_t &in, const Result_t &a)
{
onSuccess(a);
};
return ret;
}
template<typename Out_t = AVoid, typename ... Args, typename Callable_t>
FJob<AuTuple<Args...>, Out_t> JobFromTupleConsumer(/*AuConsumer<Args..., const Result_t &> */ Callable_t onSuccess)
{
FJob<AuTuple<Args...>, Out_t> ret;
ret.onSuccess = [=](const AuTuple<Args...> &in, const Out_t &a)
{
AuTupleApply(onSuccess, AuTupleCat(in, AuMakeTuple<const Out_t &>(a)));
};
return ret;
}
template<typename Out_t = AVoid, typename ... Args, typename Callable_t, typename FailureCallable_t>
FJob<AuTuple<Args...>, Out_t> JobFromTupleConsumerEx(/*AuConsumer<Args..., const Result_t &> */ Callable_t onSuccess, FailureCallable_t onFailure)
{
FJob<AuTuple<Args...>, Out_t> ret;
ret.onSuccess = [=](const AuTuple<Args...> &in, const Out_t &a)
{
AuTupleApply(onSuccess, AuTupleCat(in, AuMakeTuple<const Out_t &>(a)));
};
ret.onFailure = [=](const AuTuple<Args...> &in)
{
AuTupleApply(onFailure, in);
};
return ret;
}
template<class Info_t = AVoid, class Result_t = AVoid>
static inline FJob<Info_t, Result_t> JobFromPairConsumerEx(const AuConsumer<const Info_t &, const Result_t &> &onSuccess, const AuConsumer<const Info_t &> &onFailure)
{
FJob<Info_t, Result_t> ret;
ret.onSuccess = [=](const Info_t &in, const Result_t &a)
{
onSuccess(in, a);
};
ret.onFailure = [=](const Info_t &a)
{
onFailure(a);
};
return ret;
}
template<class Info_t = AVoid, class Result_t = AVoid>
static inline FJob<Info_t, Result_t> JobFromConsumer(const AuConsumer<const Result_t &> &onSuccess, const AuVoidFunc &onFailure)
{
FJob<Info_t, Result_t> ret;
ret.onSuccess = [=](const Info_t &in, const Result_t &a)
{
onSuccess(a);
};
ret.onFailure = [=](const Info_t &a)
{
onFailure();
};
return ret;
}
template<class Info_t = AVoid, class Result_t = AVoid, class BaseInfo_t = AVoid, class BaseResult_t = AVoid>
static inline FJob<Info_t, Result_t> JobFromDerivedJob(const FJob<BaseInfo_t, BaseResult_t> &reference)
{
FJob<Info_t, Result_t> ret;
ret.onSuccess = [=](const Info_t &in, const Result_t &a)
{
if (reference.onSuccess)
{
reference.onSuccess(in, a);
}
};
ret.onFailure = [=](const Info_t &a)
{
if (reference.onFailure)
{
reference.onFailure(a);
}
};
return ret;
}
template<typename ReturnValue_t = void, typename Arg0_t, typename ... Args>
static inline FJob<AuTuple<Arg0_t, Args...>, ReturnValue_t> JobFromTupleClazz(const AuConsumer<const Arg0_t &, const ReturnValue_t &> &onSuccess)
{
FJob<AuTuple<Arg0_t, Args...>, ReturnValue_t> ret;
ret.onSuccess = [=](const AuTuple<Arg0_t, Args...> &in, const ReturnValue_t &out)
{
onSuccess(AuGet<0>(in), out);
};
return ret;
}
template<typename ReturnValue_t = void, typename Arg0_t, typename ... Args>
static inline FJob<AuTuple<Arg0_t, Args...>, ReturnValue_t> JobFromTupleClazzEx(const AuConsumer<const Arg0_t &, const ReturnValue_t &> &onSuccess, const AuConsumer<const Arg0_t &> &onFailure)
{
FJob<AuTuple<Arg0_t, Args...>, ReturnValue_t> ret;
ret.onSuccess = [=](const AuTuple<Arg0_t, Args...> &in, const ReturnValue_t &out)
{
onSuccess(AuGet<0>(in), out);
};
ret.onFailure = [=](const AuTuple<Arg0_t, Args...> &in)
{
onFailure(AuGet<0>(in));
};
return ret;
}
#if 0
template<typename ReturnValue_t = void, typename Clazz_t, typename ... Args>
static inline FJob<AuTuple<AuSPtr<Clazz_t>, Args...>, ReturnValue_t> JobFromTupleClazz(const AuConsumer<const ReturnValue_t &> &onSuccess)
{
FJob<AuTuple<AuSPtr<Clazz_t>, Args...>, ReturnValue_t> ret;
ret.onSuccess = [=](const AuTuple<AuSPtr<Clazz_t>, Args...> &in, const ReturnValue_t &out)
{
onSuccess(out);
};
return ret;
}
template<typename ReturnValue_t = void, typename Clazz_t, typename ... Args>
static inline FJob<AuTuple<AuSPtr<Clazz_t>, Args...>, ReturnValue_t> JobFromTupleClazz(const AuConsumer<Args..., const ReturnValue_t &> &onSuccess)
{
FJob<AuTuple<AuSPtr<Clazz_t>, Args...>, ReturnValue_t> ret;
ret.onSuccess = [=](const AuTuple<AuSPtr<Clazz_t>, Args...> &in, const ReturnValue_t &out)
{
AuTupleApply(onSuccess, AuTupleCat(AuTuplePopFront(in), AuMakeTuple<const ReturnValue_t &>(out)));
};
return ret;
}
#endif
template<typename ReturnValue_t = void, typename ... Args>
static inline FJob<AuTuple<Args...>, ReturnValue_t> JobFromTupleResultConsumer(const AuConsumer<const ReturnValue_t &> &onSuccess)
{
FJob<AuTuple<Args...>, ReturnValue_t> ret;
ret.onSuccess = [=](const AuTuple<Args...> &in, const ReturnValue_t &out)
{
onSuccess(out);
};
return ret;
}
template<typename ReturnValue_t = void, typename ... Args>
static inline FJob<AuTuple<Args...>, ReturnValue_t> JobFromTuple(const AuConsumer<Args..., const ReturnValue_t &> &onSuccess)
{
FJob<AuTuple<Args...>, ReturnValue_t> ret;
ret.onSuccess = [=](const AuTuple<Args...> &in, const ReturnValue_t &out)
{
AuTupleApply(onSuccess, AuTupleCat(in, AuMakeTuple<const ReturnValue_t &>(out)));
};
return ret;
}
}

View File

@ -1,33 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Jobs.hpp
Date: 2021-11-1
Author: Reece
***/
#pragma once
namespace Aurora::Async
{
template<class Info_t = AVoid, class Result_t = AVoid>
struct FJob
{
using InfoType_t = Info_t;
using ResultType_t = Result_t;
AuFunction<void(const Info_t &, const Result_t &)> onSuccess;
AuFunction<void(const Info_t &)> onFailure;
};
template<class Info_t = AVoid, class Result_t = AVoid>
struct CJob
{
using InfoType_t = Info_t;
using ResultType_t = Result_t;
void(* onSuccess)(const Info_t &, const Result_t &);
void(* onFailure)(const Info_t &);
};
using FVoidJob = FJob<AVoid, AVoid>;
}

View File

@ -1,146 +0,0 @@
#pragma once
namespace Aurora::Async
{
#pragma region EASE_OF_READING
struct BasicWorkStdFunc : IWorkItemHandler
{
AuFunction<void()> callback;
AuFunction<void()> shutdown; // error
inline BasicWorkStdFunc(AuFunction<void()> &&callback, AuFunction<void()> &&shutdown) : callback(std::move(callback)), shutdown(std::move(shutdown))
{}
inline BasicWorkStdFunc(AuFunction<void()> &&callback) : callback(std::move(callback))
{}
inline BasicWorkStdFunc(const AuFunction<void()> &callback) : callback(callback)
{}
inline BasicWorkStdFunc(const AuFunction<void()> &callback, const AuFunction<void()> &shutdown) : callback(callback), shutdown(shutdown)
{}
private:
#if !defined(_CPPSHARP)
inline void DispatchFrame(ProcessInfo &info) override
{
try
{
callback();
}
catch (...)
{
Debug::PrintError();
}
}
inline void OnFailure() override
{
try
{
if (shutdown)
{
shutdown();
}
}
catch (...)
{
Debug::PrintError();
}
}
#endif
};
/// @hideinitializer
template<typename Frame_t = AuFunction<void()>, typename Cleanup_t = AuFunction<void()>>
struct WorkItemCallable : IWorkItemHandler
{
Frame_t frame;
Cleanup_t cleanup;
private:
void DispatchFrame(ProcessInfo &info) override
{
if constexpr (AuIsBaseOfTemplate<AuFunction, Frame_t>::value)
{
if (!frame)
{
info.type = ETickType::eFinished;
return;
}
}
frame();
info.type = ETickType::eFinished;
}
void OnFailure() override
{
if constexpr (AuIsBaseOfTemplate<AuFunction, Cleanup_t>::value)
{
if (!cleanup)
{
return;
}
}
cleanup();
}
};
#define ASYNC_ERROR(exp) { if constexpr (AuIsSame_v<T, bool>) { SysPushErrorGen(exp); return {}; } else { throw AuString(exp); } }
#define ASYNC_FINISH { if constexpr (AuIsSame_v<T, bool>) { return true; } }
template<typename T = void, typename... Args, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<T, bool> || AuIsVoid_v<T>)>
static AuFunction<T(Args&&...)> TranslateAsyncFunctionToDispatcherWithThread(WorkerPId_t id, AuFunction<void(Args...)> func)
{
if (!func) return {};
return [=](Args&&... in) -> T
{
auto work = AuMakeShared<BasicWorkStdFunc>([=]() -> void {
func(in...);
});
if (!work) ASYNC_ERROR("can't dispatch async call. out of memory");
auto workItem = NewWorkItem(id, work);
if (!workItem) ASYNC_ERROR("can't dispatch async call. out of memory");
workItem->Dispatch();
ASYNC_FINISH;
};
}
/// Async app only
template<typename T = void, typename... Args, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<T, bool> || AuIsVoid_v<T>)>
static AuFunction<T(Args&&...)> TranslateAsyncFunctionToDispatcher(AuFunction<void(Args...)> func)
{
return TranslateAsyncFunctionToDispatcherWithThread(GetAsyncApp()->GetCurrentThread(), func);
}
/// Async app only
template<typename B = void, typename T, typename... Args, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<T, bool> || AuIsVoid_v<T>)>
static AuFunction<T(AuFunction<void(const B&)>, Args...)> TranslateAsyncReturnableFunctionToDispatcherWithThread(WorkerPId_t id, AuFunction<B(Args...)> func)
{
return [=](AuFunction<T(const B&)> callback, Args... in) -> T
{
auto work = AuMakeShared<WorkPairImpl<AVoid, B>>();
if (!work) ASYNC_ERROR("can't dispatch async call; out of memory");
work.task.onProcess = [=](const AVoid &) -> B
{
if (!func) return B{};
return func(in...);
};
work.callback.onSuccess = [=](const AVoid &, const B &ret)
{
callback(ret);
};
auto workItem = NewWorkItem(id, work);
if (!workItem) ASYNC_ERROR("can't dispatch async call; out of memory");
workItem->Dispatch();
ASYNC_FINISH;
};
}
#undef ASYNC_ERROR
#undef ASYNC_FINISH
#pragma endregion EASE_OF_READING
}

View File

@ -1,86 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: TaskFrom.hpp
Date: 2021-11-1
Author: Reece
***/
#pragma once
namespace Aurora::Async
{
template<typename Info_t = AVoid, typename Out_t = AVoid, class ClazzImpl>
FTask<Info_t, Out_t> TaskFromConsumerRefT(ClazzImpl func)
{
FTask<Info_t, Out_t> ret;
ret.onFrame = [=](const Info_t &in) -> Out_t
{
if constexpr (AuIsSame_v<Out_t, AVoid>)
{
func(in);
return {};
}
else
{
return func(in);
}
};
return ret;
}
template<typename Out_t = AVoid, typename ... Args, typename Functor>
FTask<AuTuple<Args...>, Out_t> TaskFromTupleCallable(Functor func)
{
FTask<AuTuple<Args...>, Out_t> ret;
ret.onFrame = [=](const AuTuple<Args...> &in) -> Out_t
{
return AuTupleApply(func, in);
};
return ret;
}
template<typename Out_t = AVoid, typename Owner_t, typename ... Args>
FTask<AuTuple<Args...>, Out_t> TaskFromTupleCallableWithOwnerArg(AuFunction<Out_t(Args...)> func, const Owner_t &ownerToPin)
{
FTask<AuTuple<Owner_t, Args...>, Out_t> ret;
ret.onFrame = [ownerToPin, callable = func](const AuTuple<Args...> &in) -> Out_t
{
return AuTupleApply(callable, AuTupleCat(AuMakeTuple<Owner_t>(ownerToPin), in));
};
return ret;
}
template<typename Task_t, typename ReturnValue_t, typename ... Args, typename Functor>
Task_t TaskFromTupleCallableWithBindOwner(Functor func)
{
Task_t ret;
ret.onFrame = [=](const auto &in) -> ReturnValue_t
{
return AuTupleApply(func, AuTuplePopFront(in));
};
return ret;
}
template<typename Task_t, typename ReturnValue_t, typename Functor>
Task_t TaskFromTupleCallableWithBindOwner2(Functor func)
{
Task_t ret;
ret.onFrame = [=](const auto &in) -> ReturnValue_t
{
return AuTupleApply(func, AuTuplePopFront(in));
};
return ret;
}
template<typename Info_t = AVoid, typename Out_t = AVoid>
FTask<Info_t, Out_t> TaskFromVoidVoid(const AuVoidFunc &func)
{
FTask<Info_t, Out_t> ret;
ret.onFrame = [callable = func](const Info_t &in) -> Out_t
{
callable();
return {};
};
return ret;
}
}

View File

@ -1,47 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Tasks.hpp
Date: 2021-11-1
Author: Reece
***/
#pragma once
namespace Aurora::Async
{
template<class Info_t = AVoid, class Result_t = AVoid>
struct ITask
{
virtual Result_t OnFrame(const Info_t &in) const = 0;
};
template<class Info_t = AVoid, class Result_t = AVoid>
struct FTask final : ITask<Info_t, Result_t>
{
using InfoType_t = Info_t;
using ResultType_t = Result_t;
AuFunction<Result_t(const Info_t &)> onFrame;
virtual inline Result_t OnFrame(const Info_t &in) const override final
{
return onFrame(in);
}
};
template<class Info_t = AVoid, class Result_t = AVoid>
struct CTask final : ITask<Info_t, Result_t>
{
using InfoType_t = Info_t;
using ResultType_t = Result_t;
Result_t(* onFrame)(const Info_t &) = 0;
virtual inline Result_t OnFrame(const Info_t &in) const override final
{
return onFrame(in);
}
};
using FVoidTask = FTask<AVoid, AVoid>;
}

View File

@ -1,121 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: WorkBasic.hpp
Date: 2021-11-1
Author: Reece
***/
#pragma once
namespace Aurora::Async
{
/// --- THREAD POOL --
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, class a = const Job_t &, class b = Task_t &, class WorkerPId_tt = WorkerPId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerPId_tt, WorkerPId_t>)>
static AuSPtr<IWorkItem> NewWork(const WorkerPId_tt &worker, a task, b job, bool enableWait = false)
{
return worker.pool->NewWorkItem(worker, AuMakeShared<WorkPairImpl<Info_t, Result_t, Task_t>>(task, job), enableWait);
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, class a = const Job_t &, class b = Task_t &, class WorkerPId_tt = WorkerPId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerPId_tt, WorkerPId_t>)>
static AuSPtr<IWorkItem> DispatchWork(const WorkerPId_tt &worker, a task, b job, bool enableWait = false)
{
return NewWork<Info_t, Result_t, Task_t, Job_t>(worker, task, job, enableWait)->Dispatch();
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, class a, class b = Job_t, class c, class WorkerPId_tt = WorkerPId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerPId_tt, WorkerPId_t>)>
static AuSPtr<IWorkItem> NewWork(const WorkerPId_tt &worker, a task, b job, c info, bool enableWait = false)
{
return worker.pool->NewWorkItem(worker, AuMakeShared<WorkPairImpl<Info_t, Result_t, Task_t>>(task, job, info), enableWait);
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, class a, class b = Job_t, class c, class WorkerPId_tt = WorkerPId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerPId_tt, WorkerPId_t>)>
static AuSPtr<IWorkItem> DispatchWork(const WorkerPId_tt &worker, a task, b job, c info, bool enableWait = false)
{
return NewWork<Info_t, Result_t, Task_t, Job_t>(worker, task, job, info, enableWait)->Dispatch();
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, typename ClazzImpl, class a = const Job_t &, class b = const Info_t &, class WorkerPId_tt = WorkerPId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerPId_tt, WorkerPId_t>)>
AuSPtr<IWorkItem> DispatchFunctional(const WorkerPId_tt &worker, ClazzImpl task, a job, b inputParameters, bool enableWait = false)
{
return NewWork<Info_t, Result_t, Task_t, Job_t>(worker, TaskFromConsumerRefT<Info_t, Result_t>(task), job, inputParameters, enableWait);
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, typename ClazzImpl, class a = const Job_t &, class b = const Info_t &, class WorkerPId_tt = WorkerPId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerPId_tt, WorkerPId_t>)>
AuSPtr<IWorkItem> DispatchFunctor(const WorkerPId_tt &worker, ClazzImpl task, a job, b inputParameters, bool enableWait = false)
{
return NewWork<Info_t, Result_t, Task_t, Job_t>(worker, TaskFromConsumerRefT<Info_t, Result_t>(task), job, inputParameters, enableWait);
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, typename ClazzImpl, class a = const Job_t &, class b = const Info_t &, class WorkerPId_tt = WorkerPId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerPId_tt, WorkerPId_t>)>
AuSPtr<IWorkItem> DispatchVoid(const WorkerPId_tt &worker, ClazzImpl task, a job, b inputParameters, bool enableWait = false)
{
return NewWork<Info_t, Result_t, Task_t, Job_t>(worker, TaskFromVoidVoid<Info_t, Result_t>(task), job, inputParameters, enableWait);
}
/// --- ASYNC APP --
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, class a = const Job_t &, class b = Task_t &, class WorkerId_tt = WorkerId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerId_tt, WorkerId_t>)>
static AuSPtr<IWorkItem> NewWork(const WorkerId_tt &worker, a task, b job, bool enableWait = false)
{
return NewWorkItem(worker, AuMakeShared<WorkPairImpl<Info_t, Result_t, Task_t>>(task, job), enableWait);
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, class a = const Job_t &, class b = Task_t &, class WorkerId_tt = WorkerId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerId_tt, WorkerId_t>)>
static AuSPtr<IWorkItem> DispatchWork(const WorkerId_tt &worker, a task, b job, bool enableWait = false)
{
return NewWork<Info_t, Result_t, Task_t, Job_t>(worker, task, job, enableWait)->Dispatch();
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, class a, class b = Job_t, class c, class WorkerId_tt = WorkerId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerId_tt, WorkerId_t>)>
static AuSPtr<IWorkItem> NewWork(const WorkerId_tt &worker, a task, b job, c info, bool enableWait = false)
{
return NewWorkItem(worker, AuMakeShared<WorkPairImpl<Info_t, Result_t, Task_t>>(task, job, info), enableWait);
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, class a, class b = Job_t, class c, class WorkerId_tt = WorkerId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerId_tt, WorkerId_t>)>
static AuSPtr<IWorkItem> DispatchWork(const WorkerId_tt &worker, a task, b job, c info, bool enableWait = false)
{
return NewWork<Info_t, Result_t, Task_t, Job_t>(worker, task, job, info, enableWait)->Dispatch();
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, typename ClazzImpl, class a = const Job_t &, class b = const Info_t &, class WorkerId_tt = WorkerId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerId_tt, WorkerId_t>)>
AuSPtr<IWorkItem> DispatchFunctional(const WorkerId_tt &worker, ClazzImpl task, a job, b inputParameters, bool enableWait = false)
{
return NewWork<Info_t, Result_t, Task_t, Job_t>(worker, TaskFromConsumerRefT<Info_t, Result_t>(task), job, inputParameters, enableWait);
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, typename ClazzImpl, class a = const Job_t &, class b = const Info_t &, class WorkerId_tt = WorkerId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerId_tt, WorkerId_t>)>
AuSPtr<IWorkItem> DispatchFunctor(const WorkerId_tt &worker, ClazzImpl task, a job, b inputParameters, bool enableWait = false)
{
return NewWork<Info_t, Result_t, Task_t, Job_t>(worker, TaskFromConsumerRefT<Info_t, Result_t>(task), job, inputParameters, enableWait);
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, typename ClazzImpl, class a = const Job_t &, class b = const Info_t &, class WorkerId_tt = WorkerId_t, AU_TEMPLATE_ENABLE_WHEN(AuIsSame_v<WorkerId_tt, WorkerId_t>)>
AuSPtr<IWorkItem> DispatchVoid(const WorkerId_t &worker, ClazzImpl task, a job, b inputParameters, bool enableWait = false)
{
return NewWork<Info_t, Result_t, Task_t, Job_t>(worker, TaskFromVoidVoid<Info_t, Result_t>(task), job, inputParameters, enableWait);
}
template<typename ReturnValue_t = void, typename ... Args, class Clazz_t, class FunctorTask_t, class FuckYou_t >
static AuSPtr<IWorkItem> DispathSmartWork(const WorkerId_t &worker, AuSPtr<Clazz_t> owner, FunctorTask_t task, FuckYou_t job, Args ... in)
{
return DispatchWork<AuTuple<AuSPtr<Clazz_t>, Args...>, ReturnValue_t>(worker,
TaskFromTupleCallableWithBindOwner2<FTask<AuTuple<AuSPtr<Clazz_t>, Args...>, ReturnValue_t>, ReturnValue_t, FunctorTask_t>(task),
Async::JobFromTupleClazz<ReturnValue_t, AuSPtr<Clazz_t>, Args...>(job),
AuMakeTuple<AuSPtr<Clazz_t>, Args...>(AU_FWD(owner), AuForward<Args>(in)...),
false);
}
template<typename ReturnValue_t = void, typename ... Args, class Clazz_t, class FunctorTask_t, class FuckYou_t, class FuckYou2_t >
static AuSPtr<IWorkItem> DispathSmartWorkEx(const WorkerId_t &worker, AuSPtr<Clazz_t> owner, FunctorTask_t task, FuckYou_t success, FuckYou2_t failure, Args ... in)
{
return DispatchWork<AuTuple<AuSPtr<Clazz_t>, Args...>, ReturnValue_t>(worker,
TaskFromTupleCallableWithBindOwner2<FTask<AuTuple<AuSPtr<Clazz_t>, Args...>, ReturnValue_t>, ReturnValue_t, FunctorTask_t>(task),
Async::JobFromTupleClazzEx<ReturnValue_t, AuSPtr<Clazz_t>, Args...>(success, failure),
AuMakeTuple<AuSPtr<Clazz_t>, Args...>(AU_FWD(owner), AuForward<Args>(in)...),
false);
}
}

View File

@ -1,226 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: WorkPairImpl.hpp
Date: 2021-11-1
Author: Reece
***/
#pragma once
namespace Aurora::Threading::Primitives
{
class SpinLoop;
}
namespace Aurora::Async
{
struct BasicWorkStdFunc;
/// @hideinitializer
struct BasicWorkCtx : WorkPriv
{
BasicWorkCtx()
{
magic = AuConvertMagicTag32("BWOT");
opt = nullptr;
}
void *opt;
};
/// @hideinitializer
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>>
struct WorkPairImpl : IWorkItemHandler, AuEnableSharedFromThis<IWorkItemHandler>
{
WorkPairImpl() : caller_(Async::GetCurrentWorkerPId())
{}
WorkPairImpl(Task_t &&task) : task(AuMove(task)), caller_(Async::GetCurrentWorkerPId())
{}
WorkPairImpl(Task_t &&task, Job_t &&callback) : task(AuMove(task)), callback(AuMove(callback)), caller_(Async::GetCurrentWorkerPId())
{}
WorkPairImpl(const Task_t &task) : task(task), caller_(Async::GetCurrentWorkerPId())
{}
WorkPairImpl(const Task_t &task, const Job_t &callback) : task(task), callback(callback), caller_(Async::GetCurrentWorkerPId())
{}
WorkPairImpl(const Task_t &task, const Job_t &callback, const Info_t &info) : task(task), callback(callback), input(info), caller_(Async::GetCurrentWorkerPId())
{}
WorkPairImpl(Task_t &&task, const Job_t &callback, const Info_t &info) : task(AuMove(task)), callback(callback), input(info), caller_(Async::GetCurrentWorkerPId())
{}
WorkPairImpl(Task_t &&task, Job_t &&callback, const Info_t &info) : task(AuMove(task)), callback(AuMove(callback)), input(info), caller_(Async::GetCurrentWorkerPId())
{}
WorkPairImpl(Task_t &&task, Job_t &&callback, Info_t &&info) : task(AuMove(task)), callback(AuMove(callback)), input(AuMove(info)), caller_(Async::GetCurrentWorkerPId())
{}
WorkPairImpl(const Task_t &task, const Job_t &callback, Info_t &&info) : task(task), callback(callback), input(info), caller_(Async::GetCurrentWorkerPId())
{}
Info_t input;
Task_t task;
Job_t callback;
WorkPairImpl<Info_t, Result_t, Task_t, Job_t> &SetTask(const Task_t &task)
{
this->task = task;
return *this;
}
WorkPairImpl<Info_t, Result_t, Task_t, Job_t> &SetTask(const Job_t &callback)
{
this->callback = callback;
return *this;
}
private:
static constexpr bool IsCallbackPtr = AuIsPointer_v<Job_t> || AuIsBaseOfTemplate<AURORA_RUNTIME_AU_SHARED_PTR, Job_t >::value || AuIsBaseOfTemplate<AURORA_RUNTIME_AU_UNIQUE_PTR, Job_t>::value;
static constexpr bool IsTaskPtr = AuIsPointer_v<Task_t> || AuIsBaseOfTemplate<AURORA_RUNTIME_AU_SHARED_PTR, Task_t>::value || AuIsBaseOfTemplate<AURORA_RUNTIME_AU_UNIQUE_PTR, Task_t>::value;
//WorkerId_t caller;
WorkerPId_t caller_;
Threading::Primitives::SpinLock lock_;
BasicWorkCtx secretContext_;
Result_t resultValue_;
virtual void *GetPrivateData() override { return &secretContext_; }
void DispatchFrame(ProcessInfo &info) override
{
AU_LOCK_GUARD(this->lock_);
try
{
if constexpr (IsTaskPtr)
{
if (task)
{
resultValue_ = task->OnFrame(input);
}
}
else
{
resultValue_ = task.OnFrame(input);
}
task = {};
}
catch (...)
{
Debug::PrintError();
ShutdownNoLock();
return;
}
auto pin = AuSharedFromThis();
AuFunction<void()> func = [pin]()
{
try
{
pin->secretContext_.opt = &pin->resultValue_;
if constexpr (IsCallbackPtr)
{
pin->callback->onSuccess(pin->input, pin->resultValue_);
}
else
{
if (pin->callback.onSuccess)
{
pin->callback.onSuccess(pin->input,pin->resultValue_);
}
}
}
catch (...)
{
Debug::PrintError();
}
pin->callback = {};
pin->caller_ = {};
};
try
{
if (caller_ == Async::GetCurrentWorkerPId())
{
func();
}
else
{
AuFunction<void()> err = [pin]()
{
pin->CallOnFailure();
};
// TODO: this is somewhat evil. double alloc when we could reuse this
if (!caller_.pool->NewWorkItem(caller_, AuMakeShared<BasicWorkStdFunc>(func, err))->Dispatch())
{
pin->CallOnFailure();
}
}
caller_ = {};
}
catch (...)
{
Debug::PrintError();
ShutdownNoLock();
}
}
void OnFailure() override
{
AU_LOCK_GUARD(this->lock_);
ShutdownNoLock();
}
inline void ShutdownNoLock()
{
caller_ = {};
try
{
CallOnFailure();
}
catch (...)
{
Debug::PrintError();
}
callback = {};
task = {};
}
inline void CallOnFailure()
{
if constexpr (IsCallbackPtr)
{
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_FUNC, decltype(callback->onFailure)>::value)
{
if (!callback->onFailure)
{
return;
}
}
callback->onFailure(input);
}
else
{
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_FUNC, decltype(callback.onFailure)>::value)
{
if (!callback.onFailure)
{
return;
}
}
callback.onFailure(input);
}
}
};
}

View File

@ -173,7 +173,7 @@ namespace Aurora::Async
{ {
if (!AuExchange(gLockedPump, true)) if (!AuExchange(gLockedPump, true))
{ {
NewWorkItem(gMainThread.value(), AuMakeShared<BasicWorkStdFunc>(PumpSysThread))->Dispatch(); DispatchOn(gMainThread.value(), PumpSysThread);
} }
SchedNextTime(AuMSToNS<AuUInt64>(gRuntimeConfig.async.dwLegacyMainThreadSystemTickMS) + AuTime::SteadyClockNS()); SchedNextTime(AuMSToNS<AuUInt64>(gRuntimeConfig.async.dwLegacyMainThreadSystemTickMS) + AuTime::SteadyClockNS());

View File

@ -998,14 +998,11 @@ namespace Aurora::Async
AuSPtr<AuThreads::IThreadFeature> pFeature, AuSPtr<AuThreads::IThreadFeature> pFeature,
bool bNonBlock) bool bNonBlock)
{ {
auto work = AuMakeSharedThrow<BasicWorkStdFunc>(([=]() auto pWorkItem = DispatchOn({ this->SharedFromThis(), id }, [=]()
{ {
GetThreadState()->features.push_back(pFeature); GetThreadState()->features.push_back(pFeature);
pFeature->Init(); pFeature->Init();
})); });
auto pWorkItem = this->NewWorkItem(id, work)->Dispatch();
SysAssert(pWorkItem);
if (!bNonBlock) if (!bNonBlock)
{ {

View File

@ -38,6 +38,7 @@ namespace Aurora::Async
WorkItem::~WorkItem() WorkItem::~WorkItem()
{ {
//Fail(); //Fail();
} }
@ -268,7 +269,6 @@ namespace Aurora::Async
{ {
if (this->task_) if (this->task_)
{ {
try try
{ {
this->task_->DispatchFrame(info); this->task_->DispatchFrame(info);
@ -306,20 +306,7 @@ namespace Aurora::Async
IWorkItemHandler::ProcessInfo info(true); IWorkItemHandler::ProcessInfo info(true);
info.pool = this->owner_->ToThreadPool(); info.pool = this->owner_->ToThreadPool();
if (this->task_) DispatchTask(info);
{
try
{
this->task_->DispatchFrame(info);
}
catch (...)
{
// TODO: runtime config for root level exception caught behaviour
SysPushErrorCatch();
Fail();
return;
}
}
AU_LOCK_GUARD(this->lock); AU_LOCK_GUARD(this->lock);
RunAsyncLocked2(info); RunAsyncLocked2(info);
@ -417,7 +404,12 @@ namespace Aurora::Async
bool WorkItem::BlockUntilComplete() bool WorkItem::BlockUntilComplete()
{ {
if (!this->finishedEvent_) return false; if (!this->finishedEvent_) return false;
return this->owner_->WaitFor(this->worker_, AuUnsafeRaiiToShared(this->finishedEvent_.AsPointer()), 0); if (!this->worker_)
{
this->finishedEvent_->Wait();
return true;
};
return this->owner_->WaitFor(this->worker_.value(), AuUnsafeRaiiToShared(this->finishedEvent_.AsPointer()), 0);
} }
bool WorkItem::HasFinished() bool WorkItem::HasFinished()
@ -438,19 +430,19 @@ namespace Aurora::Async
bool WorkItem::Schedule() bool WorkItem::Schedule()
{ {
return Async::Schedule(this->dispatchTimeNs_, this->owner_, this->worker_, AuSharedFromThis()); return Async::Schedule(this->dispatchTimeNs_, this->owner_, this->worker_.value(), AuSharedFromThis());
} }
void WorkItem::SendOff() void WorkItem::SendOff()
{ {
if (!this->task_) if (!this->worker_)
{ {
// If we aren't actually calling a task interface, we may as well just dispatch objects waiting on us from here // If we aren't actually calling a task interface, we may as well just dispatch objects waiting on us from here
RunAsyncLocked2(); RunAsyncLocked2();
} }
else else
{ {
this->owner_->Run(this->worker_, AuSharedFromThis()); this->owner_->Run(this->worker_.value(), AuSharedFromThis());
} }
} }
@ -553,26 +545,4 @@ namespace Aurora::Async
return this->task_->GetPrivateData(); 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 {};
}
} }

View File

@ -45,7 +45,6 @@ namespace Aurora::Async
void *GetPrivateData() override; void *GetPrivateData() override;
AuOptional<void *> ToWorkResultT() override;
EWorkPrio GetPrio() override; EWorkPrio GetPrio() override;
void SetPrio(EWorkPrio prio) override; void SetPrio(EWorkPrio prio) override;
@ -62,7 +61,7 @@ namespace Aurora::Async
virtual void DispatchTask(IWorkItemHandler::ProcessInfo &info); virtual void DispatchTask(IWorkItemHandler::ProcessInfo &info);
AuSPtr<IWorkItemHandler> task_; AuSPtr<IWorkItemHandler> task_;
WorkerPId_t worker_; AuOptionalEx<WorkerPId_t> worker_;
EWorkPrio prio_ = EWorkPrio::eNormalPrio; EWorkPrio prio_ = EWorkPrio::eNormalPrio;
AuList<AuSPtr<IWorkItem>> waitOn_; AuList<AuSPtr<IWorkItem>> waitOn_;
AuList<AuSPtr<IWorkItem>> waiters_; AuList<AuSPtr<IWorkItem>> waiters_;

View File

@ -175,7 +175,7 @@ namespace Aurora::Console::Commands
} }
else else
{ {
NewWorkItem(gCommandDispatcher.value(), AuMakeShared<Async::BasicWorkStdFunc>(func))->Dispatch()->BlockUntilComplete(); DispatchOn(gCommandDispatcher.value(), func)->BlockUntilComplete();
} }
} }