[*] Improve Aurora::Async API
This commit is contained in:
parent
ad182d07e0
commit
bd5222cbfb
@ -78,6 +78,10 @@ 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;
|
||||
|
||||
virtual void *GetPrivateData() { return nullptr; }
|
||||
@ -87,7 +91,7 @@ namespace Aurora::Async
|
||||
struct FJob
|
||||
{
|
||||
std::function<void(const Info_t &, const Result_t &)> onSuccess = 0;
|
||||
std::function<void(const Info_t &, bool)> onFailure = 0;
|
||||
std::function<void(const Info_t &)> onFailure = 0;
|
||||
};
|
||||
|
||||
template<class Info_t = AVoid, class Result_t = AVoid>
|
||||
@ -110,9 +114,9 @@ namespace Aurora::Async
|
||||
{
|
||||
onSuccess(in, a);
|
||||
};
|
||||
ret.onFailure = [=](const Info_t &a, bool neverDispatched)
|
||||
ret.onFailure = [=](const Info_t &a)
|
||||
{
|
||||
onFailure(a, neverDispatched);
|
||||
onFailure(a, true);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
@ -126,7 +130,7 @@ namespace Aurora::Async
|
||||
{
|
||||
onSuccess(in, a);
|
||||
};
|
||||
ret.onFailure = [=](const Info_t &a, bool neverDispatched)
|
||||
ret.onFailure = [=](const Info_t &a)
|
||||
{
|
||||
onFailure(a);
|
||||
};
|
||||
@ -138,59 +142,57 @@ namespace Aurora::Async
|
||||
template<class Info_t = AVoid, class Result_t = AVoid>
|
||||
struct CJob
|
||||
{
|
||||
void(* onSuccess)(const Info_t &, const Result_t &); //
|
||||
void(* onFailure)(const Info_t &, bool taskNeverDispatched); // called from caller thread if taskNeverDispatched
|
||||
void(* onSuccess)(const Info_t &, const Result_t &);
|
||||
void(* onFailure)(const Info_t &);
|
||||
};
|
||||
|
||||
template<class Info_t = AVoid, class Result_t = AVoid>
|
||||
struct FTask
|
||||
{
|
||||
std::function<AuOptional<Result_t>(const Info_t &)> onFrame = 0;
|
||||
std::function<Result_t(const Info_t &)> onFrame = 0;
|
||||
};
|
||||
|
||||
using FVoidTask = FTask<AVoid, AVoid>;
|
||||
|
||||
template<class In_t = Async::AVoid>
|
||||
static inline FTask<In_t, AVoid> TaskFromConsumerRefT(const AuConsumer<const In_t &> &func)
|
||||
{
|
||||
FTask<In_t, AVoid> ret;
|
||||
ret.onFrame = [=](const In_t &a) -> AuOptional<AVoid>
|
||||
{
|
||||
func(a);
|
||||
return AVoid{};
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template<class In_t = Async::AVoid, class Out_t = Async::AVoid>
|
||||
static inline FTask<In_t, AVoid> TaskFromConsumerRefT(const AuSupplierConsumer<AuOptional<Out_t>, const In_t &> &func)
|
||||
template<class In_t = Async::AVoid, class Out_t = Async::AVoid, typename Functional_t = AuConsumer<const In_t &>>
|
||||
static inline FTask<In_t, Out_t> TaskFromConsumerRefT(const Functional_t &func)
|
||||
{
|
||||
FTask<In_t, Out_t> ret;
|
||||
ret.onFrame = [=](const In_t &a) -> AuOptional<Out_t>
|
||||
ret.onFrame = [=](const In_t &a) -> Out_t
|
||||
{
|
||||
return func(a);
|
||||
};
|
||||
return ret;
|
||||
if constexpr (std::is_same_v<Functional_t, AuConsumer<const In_t &>>)
|
||||
{
|
||||
func(a);
|
||||
return Out_t{};
|
||||
}
|
||||
|
||||
static inline FTask<AVoid, AVoid> TaskFromFunctional(const AuVoidFunc &func)
|
||||
else if constexpr (std::is_same_v<Functional_t, AuConsumer<const In_t *>>)
|
||||
{
|
||||
FTask<AVoid, AVoid> ret;
|
||||
ret.onFrame = [=](const AVoid &a) -> AuOptional<AVoid>
|
||||
func(&a);
|
||||
return Out_t{};
|
||||
}
|
||||
else if constexpr (std::is_same_v<Functional_t, AuVoidFunc>)
|
||||
{
|
||||
func();
|
||||
return AVoid{};
|
||||
return Out_t{};
|
||||
}
|
||||
else if constexpr (std::is_same_v<Functional_t, AuSupplierConsumer<Out_t, const In_t &>>)
|
||||
{
|
||||
return func(a);
|
||||
}
|
||||
else if constexpr (std::is_same_v<Functional_t, AuConsumer<const In_t &>>)
|
||||
{
|
||||
func(a);
|
||||
return Out_t{};
|
||||
}
|
||||
return Out_t{};
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class Info_t = AVoid, class Result_t = AVoid>
|
||||
struct CTask
|
||||
{
|
||||
AuOptional<Result_t>(* onFrame)(const Info_t &);
|
||||
Result_t(* onFrame)(const Info_t &);
|
||||
};
|
||||
|
||||
class IWorkItem
|
||||
@ -271,9 +273,9 @@ namespace Aurora::Async
|
||||
struct BasicWorkStdFunc : IWorkItemHandler
|
||||
{
|
||||
std::function<void()> callback;
|
||||
std::function<void()> shutdown;
|
||||
std::function<void()> shutdown; // error
|
||||
|
||||
BasicWorkStdFunc(std::function<void()> &&callback, std::function<void()> &&error) : callback(std::move(callback)), shutdown(std::move(error))
|
||||
BasicWorkStdFunc(std::function<void()> &&callback, std::function<void()> &&shutdown) : callback(std::move(callback)), shutdown(std::move(shutdown))
|
||||
{}
|
||||
|
||||
BasicWorkStdFunc(std::function<void()> &&callback) : callback(std::move(callback))
|
||||
@ -363,12 +365,22 @@ namespace Aurora::Async
|
||||
caller = GetAsyncApp()->GetCurrentThread();
|
||||
}
|
||||
|
||||
BasicWorkCallback(Task_t &&task, const Job_t &callback, const Info_t &info) : task(std::move(task)), callback(callback), input(info)
|
||||
{
|
||||
caller = GetAsyncApp()->GetCurrentThread();
|
||||
}
|
||||
|
||||
BasicWorkCallback(Task_t &&task, Job_t &&callback, const Info_t &info) : task(std::move(task)), callback(std::move(callback)), input(info)
|
||||
{
|
||||
caller = GetAsyncApp()->GetCurrentThread();
|
||||
}
|
||||
|
||||
BasicWorkCallback(Task_t &&task, Job_t &&callback, Info_t &&info) : task(std::move(task)), callback(std::move(callback)), input(std::move(info))
|
||||
{
|
||||
caller = GetAsyncApp()->GetCurrentThread();
|
||||
}
|
||||
|
||||
BasicWorkCallback(const Task_t &task, const Job_t &callback, Info_t &&info) : task(task), callback(callback), input(std::move(info))
|
||||
BasicWorkCallback(const Task_t &task, const Job_t &callback, Info_t &&info) : task(task), callback(callback), input(info)
|
||||
{
|
||||
caller = GetAsyncApp()->GetCurrentThread();
|
||||
}
|
||||
@ -398,7 +410,7 @@ namespace Aurora::Async
|
||||
WorkerId_t caller;
|
||||
|
||||
BasicWorkCtx secretContext_;
|
||||
AuOptional<Result_t> resultValue_;
|
||||
Result_t resultValue_;
|
||||
|
||||
virtual void *GetPrivateData() override { return &secretContext_; }
|
||||
|
||||
@ -427,26 +439,19 @@ namespace Aurora::Async
|
||||
{
|
||||
try
|
||||
{
|
||||
if (pin->resultValue_.has_value())
|
||||
{
|
||||
pin->secretContext_.opt = &pin->resultValue_.value();
|
||||
pin->secretContext_.opt = &pin->resultValue_;
|
||||
if constexpr (IsCallbackPtr)
|
||||
{
|
||||
pin->callback->onSuccess(pin->input, *pin->resultValue_);
|
||||
pin->callback->onSuccess(pin->input, pin->resultValue_);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pin->callback.onSuccess)
|
||||
{
|
||||
pin->callback.onSuccess(pin->input, *pin->resultValue_);
|
||||
pin->callback.onSuccess(pin->input,pin->resultValue_);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pin->CallOnFailure(false);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Debug::PrintError();
|
||||
@ -463,13 +468,13 @@ namespace Aurora::Async
|
||||
{
|
||||
std::function<void()> err = [pin]()
|
||||
{
|
||||
pin->CallOnFailure(false);
|
||||
pin->CallOnFailure();
|
||||
};
|
||||
|
||||
// TODO: this is somewhat evil. double alloc when we could reuse this
|
||||
if (!NewWorkItem(caller, AuMakeShared<BasicWorkStdFunc>(func, err))->Dispatch())
|
||||
{
|
||||
pin->CallOnFailure(true);
|
||||
pin->CallOnFailure();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -484,7 +489,7 @@ namespace Aurora::Async
|
||||
{
|
||||
try
|
||||
{
|
||||
CallOnFailure(true);
|
||||
CallOnFailure();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -492,7 +497,7 @@ namespace Aurora::Async
|
||||
}
|
||||
}
|
||||
|
||||
void CallOnFailure(bool fail)
|
||||
void CallOnFailure()
|
||||
{
|
||||
if constexpr (IsCallbackPtr)
|
||||
{
|
||||
@ -504,7 +509,7 @@ namespace Aurora::Async
|
||||
}
|
||||
}
|
||||
|
||||
callback->onFailure(input, fail);
|
||||
callback->onFailure(input);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -515,7 +520,7 @@ namespace Aurora::Async
|
||||
return;
|
||||
}
|
||||
}
|
||||
callback.onFailure(input, fail);
|
||||
callback.onFailure(input);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -582,13 +587,13 @@ namespace Aurora::Async
|
||||
}
|
||||
|
||||
template<typename B = void, typename T, typename... Args, AU_TEMPLATE_ENABLE_WHEN(std::is_same_v<T, bool> || std::is_void<T>::value)>
|
||||
static std::function<T(std::function<void(const B&)>, Args...)> TranslateAsyncReturnableFunctionToDispatcherWithThread(WorkerId_t id, std::function<AuOptional<B>(Args...)> func)
|
||||
static std::function<T(std::function<void(const B&)>, Args...)> TranslateAsyncReturnableFunctionToDispatcherWithThread(WorkerId_t id, std::function<B(Args...)> func)
|
||||
{
|
||||
return [=](std::function<T(const B&)> callback, Args... in) -> T
|
||||
{
|
||||
auto work = AuMakeShared<BasicWorkCallback<AVoid, B>>();
|
||||
if (!work) ASYNC_ERROR("can't dispatch async call; out of memory");
|
||||
work.task.onProcess = [=](const AVoid &) -> AuOptional<B>
|
||||
work.task.onProcess = [=](const AVoid &) -> B
|
||||
{
|
||||
if (!func) return B{};
|
||||
return func(in...);
|
||||
@ -604,16 +609,40 @@ namespace Aurora::Async
|
||||
};
|
||||
}
|
||||
|
||||
template<typename B = void, typename T, typename... Args, AU_TEMPLATE_ENABLE_WHEN(std::is_same_v<T, bool> || std::is_void<T>::value)>
|
||||
static std::function<T(std::function<void(const B&)>, Args...)> TranslateAsyncReturnableFunctionToDispatcher(std::function<AuOptional<B>(Args...)> func)
|
||||
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>>
|
||||
static AuSPtr<Async::IWorkItem> NewBasicWorkCallback(const WorkerId_t &worker, const Task_t &task, const Job_t &job, bool enableWait = false)
|
||||
{
|
||||
return TranslateAsyncReturnableFunctionToDispatcherWithThread(GetAsyncApp()->GetCurrentThread(), func);
|
||||
return Async::NewWorkItem(worker, AuMakeShared<Async::BasicWorkCallback<Info_t, Result_t, Task_t>>(std::move(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>>
|
||||
static AuSPtr<Async::IWorkItem> DispatchBasicWorkCallback(const WorkerId_t &worker, const Task_t &task, const Job_t &job, bool enableWait = false)
|
||||
{
|
||||
return Async::NewWorkItem(worker, AuMakeShared<Async::BasicWorkCallback<Info_t, Result_t>>(task, job), enableWait)->Dispatch();
|
||||
return NewBasicWorkCallback<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>>
|
||||
static AuSPtr<Async::IWorkItem> NewBasicWorkCallback(const WorkerId_t &worker, Task_t &&task, const Job_t &job, bool enableWait = false)
|
||||
{
|
||||
return Async::NewWorkItem(worker, AuMakeShared<Async::BasicWorkCallback<Info_t, Result_t, Task_t>>(std::move(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>>
|
||||
static AuSPtr<Async::IWorkItem> DispatchBasicWorkCallback(const WorkerId_t &worker, Task_t &&task, const Job_t &job, bool enableWait = false)
|
||||
{
|
||||
return NewBasicWorkCallback<Info_t, Result_t, Task_t, Job_t>(worker, std::move(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>>
|
||||
static AuSPtr<Async::IWorkItem> NewBasicWorkCallback(const WorkerId_t &worker, Task_t &&task, Job_t &&job, bool enableWait = false)
|
||||
{
|
||||
return Async::NewWorkItem(worker, AuMakeShared<Async::BasicWorkCallback<Info_t, Result_t, Task_t>>(std::move(task), std::move(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>>
|
||||
static AuSPtr<Async::IWorkItem> NBasicWorkCallback(const WorkerId_t &worker, Task_t &&task, Job_t &&job, bool enableWait = false)
|
||||
{
|
||||
return NewBasicWorkCallback<Info_t, Result_t, Task_t, Job_t>(worker, std::move(task), std::move(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>>
|
||||
@ -621,9 +650,16 @@ namespace Aurora::Async
|
||||
{
|
||||
// TOOD: use faster object if job parguments are invalid
|
||||
// It would be nice if we didn't have to drag the job callback pair around with us
|
||||
return Async::NewWorkItem(worker, AuMakeShared<Async::BasicWorkCallback<Info_t, Result_t>>(task, job, inputParameters), enableWait)->Dispatch();
|
||||
return Async::NewWorkItem(worker, AuMakeShared<Async::BasicWorkCallback<Info_t, Result_t, Task_t>>(task, job, inputParameters), 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>
|
||||
AuSPtr<Aurora::Async::IWorkItem> DispatchFunctional(const WorkerId_t &worker, ClazzImpl task, const Job_t &job, const Info_t &inputParameters, bool enableWait = false)
|
||||
{
|
||||
return Async::DispatchBasicWorkCallback<Info_t, Result_t, Task_t, Job_t>(worker, Async::TaskFromConsumerRefT<Info_t, Result_t>(task), job, inputParameters, enableWait);
|
||||
}
|
||||
|
||||
|
||||
#undef ASYNC_ERROR
|
||||
#undef ASYNC_FINISH
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user