AuroraRuntime/Include/Aurora/Async/Async.hpp

194 lines
5.9 KiB
C++
Raw Normal View History

2021-06-27 21:25:29 +00:00
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Async.hpp
2021-09-06 10:58:08 +00:00
Date: 2021-7-14
2021-06-27 21:25:29 +00:00
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<IWorkItem> NewWorkItem(const WorkerId_t &worker, const AuSPtr<IWorkItemHandler> &task, bool supportsBlocking = false);
AUKN_SYM AuSPtr<IWorkItem> NewWorkItem(const WorkerPId_t &worker, const AuSPtr<IWorkItemHandler> &task, bool supportsBlocking = false);
2021-06-27 21:25:29 +00:00
/// Async app only | Thread pools must use the IThreadPool::NewFence function
AUKN_SYM AuSPtr<IWorkItem> NewFence();
2021-06-27 21:25:29 +00:00
/// Allocates a new thread pool for usage
AUKN_SYM AuSPtr<IThreadPool> NewThreadPool();
// TODO: move the following trash out of here
// the following is mostly old trash
#pragma region EASE_OF_READING
2021-06-27 21:25:29 +00:00
struct BasicWorkStdFunc : IWorkItemHandler
{
AuFunction<void()> callback;
AuFunction<void()> shutdown; // error
BasicWorkStdFunc(AuFunction<void()> &&callback, AuFunction<void()> &&shutdown) : callback(std::move(callback)), shutdown(std::move(shutdown))
2021-06-27 21:25:29 +00:00
{}
BasicWorkStdFunc(AuFunction<void()> &&callback) : callback(std::move(callback))
2021-06-27 21:25:29 +00:00
{}
BasicWorkStdFunc(const AuFunction<void()> &callback) : callback(callback)
2021-06-27 21:25:29 +00:00
{}
BasicWorkStdFunc(const AuFunction<void()> &callback, const AuFunction<void()> &shutdown) : callback(callback), shutdown(shutdown)
2021-06-27 21:25:29 +00:00
{}
private:
2021-09-06 10:58:08 +00:00
#if !defined(_CPPSHARP)
void DispatchFrame(ProcessInfo &info) override
{
2021-06-27 21:25:29 +00:00
try
{
callback();
}
2021-06-27 21:25:29 +00:00
catch (...)
{
Debug::PrintError();
}
}
void Shutdown() override
2021-06-27 21:25:29 +00:00
{
try
{
if (shutdown)
{
shutdown();
}
}
2021-06-27 21:25:29 +00:00
catch (...)
{
Debug::PrintError();
}
}
2021-09-06 10:58:08 +00:00
#endif
2021-06-27 21:25:29 +00:00
};
2021-09-06 10:58:08 +00:00
2021-09-06 10:58:08 +00:00
#if !defined(_CPPSHARP)
/// @hideinitializer
template<typename Frame_t = AuFunction<void()>, typename Cleanup_t = AuFunction<void()>>
struct WorkItemCallable : IWorkItemHandler
2021-06-27 21:25:29 +00:00
{
Frame_t frame;
Cleanup_t cleanup;
private:
void DispatchFrame(ProcessInfo &info) override
{
if constexpr (AuIsBaseOfTemplate<Frame_t, decltype(frame)>::value)
{
if (!frame)
{
info.type = IWorkItemHandler::EProcessNext::eFinished;
return;
}
}
2021-06-27 21:25:29 +00:00
frame();
info.type = IWorkItemHandler::EProcessNext::eFinished;
}
void Shutdown() override
{
if constexpr (AuIsBaseOfTemplate<Cleanup_t, decltype(cleanup)>::value)
{
if (!cleanup)
{
return;
}
}
2021-06-27 21:25:29 +00:00
cleanup();
}
};
#define ASYNC_ERROR(exp) { if constexpr (std::is_same_v<T, bool>) { SysPushErrorGen(exp); return {}; } else { throw std::string(exp); } }
#define ASYNC_FINISH { if constexpr (std::is_same_v<T, bool>) { return true; } }
2021-09-29 08:02:27 +00:00
template<typename T = void, typename... Args, AU_TEMPLATE_ENABLE_WHEN(std::is_same_v<T, bool> || std::is_void<T>::value)>
static AuFunction<T(Args&&...)> TranslateAsyncFunctionToDispatcherWithThread(WorkerId_t id, AuFunction<void(Args...)> func)
2021-06-27 21:25:29 +00:00
{
if (!func) return {};
return [=](Args&&... in) -> T
2021-07-05 13:35:13 +00:00
{
2021-09-06 10:58:08 +00:00
auto work = AuMakeShared<BasicWorkStdFunc>([=]() -> void {
2021-07-05 13:35:13 +00:00
func(in...);
});
if (!work) ASYNC_ERROR("can't dispatch async call. out of memory");
2021-09-29 08:02:27 +00:00
auto workItem = NewWorkItem(id, work);
if (!workItem) ASYNC_ERROR("can't dispatch async call. out of memory");
2021-07-05 13:35:13 +00:00
workItem->Dispatch();
2021-09-29 08:02:27 +00:00
ASYNC_FINISH;
2021-07-05 13:35:13 +00:00
};
}
2021-09-29 08:02:27 +00:00
/// Async app only
2021-09-29 08:02:27 +00:00
template<typename T = void, typename... Args, AU_TEMPLATE_ENABLE_WHEN(std::is_same_v<T, bool> || std::is_void<T>::value)>
static AuFunction<T(Args&&...)> TranslateAsyncFunctionToDispatcher(AuFunction<void(Args...)> func)
2021-07-05 13:35:13 +00:00
{
return TranslateAsyncFunctionToDispatcherWithThread(GetAsyncApp()->GetCurrentThread(), func);
2021-09-29 08:02:27 +00:00
}
/// Async app only
2021-09-29 08:02:27 +00:00
template<typename B = void, typename T, typename... Args, AU_TEMPLATE_ENABLE_WHEN(std::is_same_v<T, bool> || std::is_void<T>::value)>
static AuFunction<T(AuFunction<void(const B&)>, Args...)> TranslateAsyncReturnableFunctionToDispatcherWithThread(WorkerId_t id, AuFunction<B(Args...)> func)
2021-09-29 08:02:27 +00:00
{
return [=](AuFunction<T(const B&)> callback, Args... in) -> T
2021-07-05 13:35:13 +00:00
{
auto work = AuMakeShared<WorkPairImpl<AVoid, B>>();
2021-09-29 08:02:27 +00:00
if (!work) ASYNC_ERROR("can't dispatch async call; out of memory");
2021-10-18 12:53:47 +00:00
work.task.onProcess = [=](const AVoid &) -> B
2021-07-05 13:35:13 +00:00
{
if (!func) return B{};
2021-07-05 13:35:13 +00:00
return func(in...);
};
work.callback.onSuccess = [=](const AVoid &, const B &ret)
{
callback(ret);
};
2021-09-29 08:02:27 +00:00
auto workItem = NewWorkItem(id, work);
if (!workItem) ASYNC_ERROR("can't dispatch async call; out of memory");
2021-07-05 13:35:13 +00:00
workItem->Dispatch();
2021-09-29 08:02:27 +00:00
ASYNC_FINISH;
2021-07-05 13:35:13 +00:00
};
2021-06-27 21:25:29 +00:00
}
2021-09-29 08:02:27 +00:00
#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