[+] Coroutine interopability
This commit is contained in:
parent
a0794a2cc9
commit
fae92993be
@ -7,6 +7,11 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
struct FutureAccessor;
|
||||
}
|
||||
|
||||
template<typename T, typename Error_t = void>
|
||||
struct AuFuture : AuEnableSharedFromThis<AuFuture<T, Error_t>>
|
||||
{
|
||||
@ -174,12 +179,39 @@ public:
|
||||
return pRet;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
friend struct __detail::FutureAccessor;
|
||||
|
||||
CppFun<T>::B &GetValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
bool WaitOn()
|
||||
{
|
||||
this->event->Wait();
|
||||
return this->bComplete;
|
||||
}
|
||||
|
||||
bool IsFinished()
|
||||
{
|
||||
return this->bComplete || this->bFailed;
|
||||
}
|
||||
|
||||
AuThreading::IWaitable *GetWaitOnInterface()
|
||||
{
|
||||
return this->event.AsPointer();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void SubmitComplete()
|
||||
{
|
||||
if (AuAsync::GetCurrentWorkerPId() == this->pid)
|
||||
{
|
||||
this->event->Set();
|
||||
|
||||
if (!this->onFailure && !this->callback)
|
||||
{
|
||||
DoWaterFalls();
|
||||
@ -262,17 +294,23 @@ private:
|
||||
AuDebug::DecMemoryCrunch();
|
||||
}
|
||||
|
||||
AuFuture()
|
||||
AuFuture() :
|
||||
event(false, false, true)
|
||||
{
|
||||
this->pid = AuAsync::GetCurrentWorkerPId();
|
||||
}
|
||||
|
||||
AuFuture(AuConsumer<Move_t> callback) : callback(callback)
|
||||
AuFuture(AuConsumer<Move_t> callback) :
|
||||
callback(callback),
|
||||
event(false, false, true)
|
||||
{
|
||||
this->pid = AuAsync::GetCurrentWorkerPId();
|
||||
}
|
||||
|
||||
AuFuture(AuConsumer<Move_t> callback, ErrorCallback_f onFailure) : callback(callback), onFailure(onFailure)
|
||||
AuFuture(AuConsumer<Move_t> callback, ErrorCallback_f onFailure) :
|
||||
callback(callback),
|
||||
onFailure(onFailure),
|
||||
event(false, false, true)
|
||||
{
|
||||
this->pid = AuAsync::GetCurrentWorkerPId();
|
||||
}
|
||||
@ -280,6 +318,7 @@ private:
|
||||
CppFun<T>::B value;
|
||||
ErrorStore_t errorValue;
|
||||
AuThreadPrimitives::Mutex mutex;
|
||||
AuThreadPrimitives::Event event;
|
||||
CompleteCallback_f callback;
|
||||
ErrorCallback_f onFailure;
|
||||
AuOptionalEx<AuAsync::WorkerPId_t> pid; // todo: make weak?
|
||||
@ -507,4 +546,199 @@ private:
|
||||
bool bFailed {};
|
||||
};
|
||||
|
||||
using AuSharedWaterfall = AuWaterfall;
|
||||
using AuSharedWaterfall = AuSPtr<AuWaterfall>;
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
struct FutureAccessor
|
||||
{
|
||||
template<typename A, typename B>
|
||||
static auto &GetValue(AuFuture<A, B> &future)
|
||||
{
|
||||
return future.GetValue();
|
||||
}
|
||||
|
||||
template<typename A, typename B>
|
||||
static bool WaitOn(AuFuture<A, B> &future)
|
||||
{
|
||||
return future.GetValue();
|
||||
}
|
||||
|
||||
template<typename A, typename B>
|
||||
static bool IsFinished(AuFuture<A, B> &future)
|
||||
{
|
||||
return future.bComplete || future.bFailed;
|
||||
}
|
||||
|
||||
template<typename A, typename B>
|
||||
static AuThreading::IWaitable *GetWaitOnInterface(AuFuture<A, B> &future)
|
||||
{
|
||||
return future.event.AsPointer();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(AU_LANG_CPP_17) || defined(AU_LANG_CPP_14)
|
||||
#if !defined(AU_HasCoRoutinedNoIncludeIfAvailable)
|
||||
#define AU_HasCoRoutinedNoIncludeIfAvailable
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(AU_HasCoRoutinedIncluded)
|
||||
#define __AUHAS_COROUTINES_CO_AWAIT
|
||||
#else
|
||||
#if !defined(AU_HasCoRoutinedNoIncludeIfAvailable)
|
||||
#include <coroutine>
|
||||
#endif
|
||||
|
||||
#define __AUHAS_COROUTINES_CO_AWAIT
|
||||
#endif
|
||||
|
||||
#if defined(__AUHAS_COROUTINES_CO_AWAIT)
|
||||
|
||||
namespace std
|
||||
{
|
||||
#if !defined(AU_HasVoidCoRoutineTraitsAvailable)
|
||||
|
||||
template<>
|
||||
struct coroutine_traits<void>
|
||||
{
|
||||
struct promise_type
|
||||
{
|
||||
void get_return_object()
|
||||
{ }
|
||||
|
||||
void set_exception(exception_ptr const &) noexcept
|
||||
{ }
|
||||
|
||||
std::suspend_always initial_suspend() noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::suspend_always final_suspend() noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void return_void() noexcept
|
||||
{ }
|
||||
|
||||
void unhandled_exception()
|
||||
{ }
|
||||
};
|
||||
};
|
||||
|
||||
template<class... T>
|
||||
struct coroutine_traits<void, T...>
|
||||
{
|
||||
struct promise_type
|
||||
{
|
||||
void get_return_object()
|
||||
{ }
|
||||
|
||||
void set_exception(exception_ptr const &) noexcept
|
||||
{ }
|
||||
|
||||
std::suspend_always initial_suspend() noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::suspend_always final_suspend() noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void return_void() noexcept
|
||||
{ }
|
||||
|
||||
void unhandled_exception()
|
||||
{ }
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
template <typename A, typename B>
|
||||
struct Awaitable
|
||||
{
|
||||
AuSharedFuture<A, B> pFuture;
|
||||
|
||||
bool await_ready()
|
||||
{
|
||||
return __detail::FutureAccessor::IsFinished(*pFuture.get());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void await_suspend(T h)
|
||||
{
|
||||
pFuture->OnComplete([=]()
|
||||
{
|
||||
h.resume();
|
||||
});
|
||||
|
||||
pFuture->OnFailure([=]()
|
||||
{
|
||||
h.resume();
|
||||
});
|
||||
}
|
||||
|
||||
A await_resume()
|
||||
{
|
||||
return __detail::FutureAccessor::GetValue(*pFuture.get());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename B>
|
||||
struct AwaitableVoid
|
||||
{
|
||||
AuSharedFuture<void, B> pFuture;
|
||||
|
||||
bool await_ready()
|
||||
{
|
||||
return __detail::FutureAccessor::IsFinished(*pFuture.get());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void await_suspend(T h)
|
||||
{
|
||||
pFuture->OnComplete([=]()
|
||||
{
|
||||
h.resume();
|
||||
});
|
||||
|
||||
pFuture->OnFailure([=]()
|
||||
{
|
||||
h.resume();
|
||||
});
|
||||
}
|
||||
|
||||
void await_resume()
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(__AUHAS_COROUTINES_CO_AWAIT)
|
||||
|
||||
template <typename A, typename B, AU_TEMPLATE_ENABLE_WHEN(!AuIsVoid_v<A>)>
|
||||
inline auto operator co_await (const AuSharedFuture<A, B> &pFuture)
|
||||
{
|
||||
SysAssert(pFuture);
|
||||
return __detail::Awaitable<A, B> { pFuture };
|
||||
}
|
||||
|
||||
template <typename A, typename B, AU_TEMPLATE_ENABLE_WHEN(AuIsVoid_v<A>)>
|
||||
inline auto operator co_await (const AuSharedFuture<A, B> &pFuture)
|
||||
{
|
||||
SysAssert(pFuture);
|
||||
return __detail::AwaitableVoid<B> { pFuture };
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user