#pragma once namespace Aurora::Async { #pragma region EASE_OF_READING struct BasicWorkStdFunc : IWorkItemHandler { AuFunction callback; AuFunction shutdown; // error BasicWorkStdFunc(AuFunction &&callback, AuFunction &&shutdown) : callback(std::move(callback)), shutdown(std::move(shutdown)) {} BasicWorkStdFunc(AuFunction &&callback) : callback(std::move(callback)) {} BasicWorkStdFunc(const AuFunction &callback) : callback(callback) {} BasicWorkStdFunc(const AuFunction &callback, const AuFunction &shutdown) : callback(callback), shutdown(shutdown) {} private: #if !defined(_CPPSHARP) void DispatchFrame(ProcessInfo &info) override { try { callback(); } catch (...) { Debug::PrintError(); } } void Shutdown() override { try { if (shutdown) { shutdown(); } } catch (...) { Debug::PrintError(); } } #endif }; /// @hideinitializer template, typename Cleanup_t = AuFunction> struct WorkItemCallable : IWorkItemHandler { Frame_t frame; Cleanup_t cleanup; private: void DispatchFrame(ProcessInfo &info) override { if constexpr (AuIsBaseOfTemplate::value) { if (!frame) { info.type = IWorkItemHandler::EProcessNext::eFinished; return; } } frame(); info.type = IWorkItemHandler::EProcessNext::eFinished; } void Shutdown() override { if constexpr (AuIsBaseOfTemplate::value) { if (!cleanup) { return; } } cleanup(); } }; #define ASYNC_ERROR(exp) { if constexpr (AuIsSame_v) { SysPushErrorGen(exp); return {}; } else { throw AuString(exp); } } #define ASYNC_FINISH { if constexpr (AuIsSame_v) { return true; } } template || AuIsVoid_v)> static AuFunction TranslateAsyncFunctionToDispatcherWithThread(WorkerId_t id, AuFunction func) { if (!func) return {}; return [=](Args&&... in) -> T { auto work = AuMakeShared([=]() -> 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 || AuIsVoid_v)> static AuFunction TranslateAsyncFunctionToDispatcher(AuFunction func) { return TranslateAsyncFunctionToDispatcherWithThread(GetAsyncApp()->GetCurrentThread(), func); } /// Async app only template || AuIsVoid_v)> static AuFunction, Args...)> TranslateAsyncReturnableFunctionToDispatcherWithThread(WorkerId_t id, AuFunction func) { return [=](AuFunction callback, Args... in) -> T { auto work = AuMakeShared>(); 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 }