Files
2025-05-18 13:04:45 +08:00

120 lines
3.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
THIRD_PARTY_INCLUDES_START
#include "continuable/continuable.hpp"
THIRD_PARTY_INCLUDES_END
#include "Async/Async.h"
#include "Async/TaskGraphInterfaces.h"
#include "Util.h"
typedef cti::continuable<int32> AsyncInt;
// This is temporary and will eventually go away
struct TEXTUREGRAPHENGINE_API ActionResult
{
std::exception_ptr ExInner; /// Original exception that was raised by the action
int32 ErrorCode = 0; /// What is the error code
TMap<FString, FString> Metadata; /// Additional metadata that may be associated with an action result.
/// This can be used to 'send back' a lot of useful information
explicit ActionResult(std::exception_ptr Ex = nullptr, int32 ErrCode = 0) : ExInner(Ex), ErrorCode(ErrCode) {}
FORCEINLINE bool IsOK() const { return ErrorCode == 0 && !ExInner; }
};
typedef std::shared_ptr<ActionResult> ActionResultPtr;
typedef cti::continuable<ActionResultPtr> AsyncActionResultPtr;
//////////////////////////////////////////////////////////////////////////
struct TEXTUREGRAPHENGINE_API PromiseUtil
{
////////////////////////////////////////////////////////////////////////////
///// Static functions
////////////////////////////////////////////////////////////////////////////
static auto OnThread(ENamedThreads::Type ThreadType);
//////////////////////////////////////////////////////////////////////////
/// Inline functions
//////////////////////////////////////////////////////////////////////////
template<typename T>
static FORCEINLINE cti::continuable<T> OnThread(ENamedThreads::Type ThreadType, T&& Args)
{
return cti::make_continuable<T>([ThreadType, args = std::forward<T>(Args)](auto&& Promise) mutable
{
AsyncTask(ThreadType, [args = std::forward<T>(args), promise = std::forward<decltype(Promise)>(Promise)]() mutable
{
promise.set_value(std::forward<T>(args));
});
});
}
template<typename T>
static cti::continuable<T> WrapResolvePromiseOnThread(ENamedThreads::Type ThreadType, TUniqueFunction<cti::continuable<T>()> callback)
{
return cti::make_continuable<int32>([=, callback = std::move(callback)](auto&& promise) mutable
{
return callback().then([=, FWD_PROMISE(promise)](T result) mutable
{
Util::OnThread(ThreadType, [=, FWD_PROMISE(promise)]() mutable
{
promise.set_value(result);
});
});
});
}
static AsyncInt OnBackgroundThread()
{
return cti::make_continuable<int32>([](auto&& Promise)
{
AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [promise = std::forward<decltype(Promise)>(Promise)]() mutable
{
promise.set_value(0);
});
});
}
static AsyncInt OnGameThread()
{
if (IsInGameThread())
return cti::make_ready_continuable(0);
return cti::make_continuable<int32>([](auto&& Promise)
{
AsyncTask(ENamedThreads::GameThread, [promise = std::forward<decltype(Promise)>(Promise)]() mutable
{
promise.set_value(0);
});
});
}
template<typename T>
static cti::continuable<T> OnGameThread(T&& Arg)
{
if (IsInGameThread())
return cti::make_ready_continuable(std::forward<T>(Arg));
return OnThread(ENamedThreads::GameThread, std::forward<T>(Arg));
}
static AsyncInt OnRenderingThread()
{
if (IsInRenderingThread())
return cti::make_ready_continuable(0);
return cti::make_continuable<int32>([](auto&& Promise)
{
AsyncTask(ENamedThreads::ActualRenderingThread, [promise = std::forward<decltype(Promise)>(Promise)]() mutable
{
promise.set_value(0);
});
});
}
};
#define FWD_PROMISE(p) p = std::forward<decltype(p)>(p)