/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: Async.hpp Date: 2021-7-14 Author: Reece ***/ #pragma once #include "AsyncTypes.hpp" #include "IWorkItem.hpp" #include "IWorkItemHandler.hpp" #include "IThreadPool.hpp" #include "IAsyncApp.hpp" #include "Jobs.hpp" #include "Tasks.hpp" namespace Aurora::Async { AUKN_SYM IAsyncApp *GetAsyncApp(); /// AUKN_SYM WorkerPId_t GetCurrentWorkerPId(); /// Async app only | Thread pools must use the IThreadPool::NewFence function AUKN_SYM AuSPtr NewWorkItem(const WorkerId_t &worker, const AuSPtr &task, bool supportsBlocking = false); AUKN_SYM AuSPtr NewWorkItem(const WorkerPId_t &worker, const AuSPtr &task, bool supportsBlocking = false); /// Async app only | Thread pools must use the IThreadPool::NewFence function AUKN_SYM AuSPtr NewFence(); /// Allocates a new thread pool for usage AUKN_SYM AuSPtr NewThreadPool(); // TODO: move the following trash out of here // the following is mostly old trash #pragma region EASE_OF_READING struct BasicWorkStdFunc : IWorkItemHandler { AuFunction callback; AuFunction shutdown; // error BasicWorkStdFunc(AuFunction &&callback, AuFunction &&shutdown) : callback(AuMove(callback)), shutdown(AuMove(shutdown)) {} BasicWorkStdFunc(AuFunction &&callback) : callback(AuMove(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 }; #if !defined(_CPPSHARP) /// @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 #endif #pragma endregion EASE_OF_READING } #if !defined(_CPPSHARP) #include "JobFrom.hpp" #include "TaskFrom.hpp" #include "WorkPairImpl.hpp" #include "WorkBasic.hpp" #endif