[+] Futures with an error value

[+] Added (made public) AuFuture::CompleteCallback_f
[+] Added (made public) AuFuture::ErrorCallback_f
This commit is contained in:
Reece Wilson 2023-05-25 02:38:41 +01:00
parent 7cf042d99c
commit 26f581736a

View File

@ -7,8 +7,8 @@
***/
#pragma once
template<typename T>
struct AuFuture : AuEnableSharedFromThis<AuFuture<T>>
template<typename T, typename Error_t = void>
struct AuFuture : AuEnableSharedFromThis<AuFuture<T, Error_t>>
{
private:
template <typename A>
@ -27,8 +27,13 @@ private:
using Move_t = AuConditional_t<AuIsVoid_v<T>, typename CppFun<T>::B &&, T>;
using CompleteCallback_f = AuConditional_t<AuIsVoid_v<T>, AuVoidFunc, AuConsumer<Move_t>>;
using Move2_t = AuConditional_t<AuIsVoid_v<Error_t>, typename CppFun<Error_t>::B &&, Error_t>;
using ErrorStore_t = AuConditional_t<AuIsVoid_v<Error_t>, typename CppFun<Error_t>::B, Error_t>;
public:
using CompleteCallback_f = AuConditional_t<AuIsVoid_v<T>, AuVoidFunc, AuConsumer<Move_t>>;
using ErrorCallback_f = AuConditional_t<AuIsVoid_v<Error_t>, AuVoidFunc, AuConsumer<Move2_t>>;
AU_NO_COPY_NO_MOVE(AuFuture);
void OnComplete(CompleteCallback_f callback)
@ -38,6 +43,7 @@ public:
if (this->bComplete)
{
SysAssert(!AuExchange(this->bDoneCb, true), "Future has already called a completion callback");
if constexpr (AuIsVoid_v<T>)
{
callback();
@ -64,14 +70,23 @@ public:
}
}
void OnFailure(AuVoidFunc onFailure)
void OnFailure(ErrorCallback_f onFailure)
{
AU_LOCK_GUARD(this->mutex);
if (this->bFailed)
{
SysAssert(!AuExchange(this->bDoneCb, true), "Future has already called a completion callback");
onFailure();
if constexpr (AuIsVoid_v<Error_t>)
{
onFailure();
}
else
{
onFailure(this->errorValue);
}
DoWaterFalls();
return;
}
@ -112,6 +127,19 @@ public:
SubmitComplete();
}
template<typename T1 = Error_t, AuEnableIf_t<!AuIsVoid_v<T1>> * = nullptr>
void Fail(Move2_t error)
{
AU_LOCK_GUARD(this->mutex);
SysAssert(!AuExchange(this->bDone, true), "Future has already finished");
this->errorValue = AuMove(error);
this->bFailed = true;
SubmitComplete();
}
template<typename T1 = Error_t, AuEnableIf_t<AuIsVoid_v<T1>> * = nullptr>
void Fail()
{
AU_LOCK_GUARD(this->mutex);
@ -122,26 +150,26 @@ public:
SubmitComplete();
}
static AuSPtr<AuFuture<T>> New()
static AuSPtr<AuFuture<T, Error_t>> New()
{
AuDebug::AddMemoryCrunch();
auto pRet = AuSPtr<AuFuture<T>>(new AuFuture(), AuDefaultDeleter<AuFuture<T>> {});
auto pRet = AuSPtr<AuFuture<T, Error_t>>(new AuFuture(), AuDefaultDeleter<AuFuture<T, Error_t>> {});
AuDebug::DecMemoryCrunch();
return pRet;
}
static AuSPtr<AuFuture<T>> New(AuConsumer<Move_t> callback)
static AuSPtr<AuFuture<T, Error_t>> New(AuConsumer<Move_t> callback)
{
AuDebug::AddMemoryCrunch();
auto pRet = AuSPtr<AuFuture<T>>(new AuFuture(callback), AuDefaultDeleter<AuFuture<T>> {});
auto pRet = AuSPtr<AuFuture<T, Error_t>>(new AuFuture(callback), AuDefaultDeleter<AuFuture<T, Error_t>> {});
AuDebug::DecMemoryCrunch();
return pRet;
}
static AuSPtr<AuFuture<T>> New(AuConsumer<Move_t> callback, AuVoidFunc onFailure)
static AuSPtr<AuFuture<T, Error_t>> New(AuConsumer<Move_t> callback, ErrorCallback_f onFailure)
{
AuDebug::AddMemoryCrunch();
auto pRet = AuSPtr<AuFuture<T>>(new AuFuture(callback, onFailure), AuDefaultDeleter<AuFuture<T>> {});
auto pRet = AuSPtr<AuFuture<T, Error_t>>(new AuFuture(callback, onFailure), AuDefaultDeleter<AuFuture<T, Error_t>> {});
AuDebug::DecMemoryCrunch();
return pRet;
}
@ -178,7 +206,14 @@ private:
{
if (auto callback = AuExchange(this->onFailure, {}))
{
callback();
if constexpr (AuIsVoid_v<Error_t>)
{
callback();
}
else
{
callback(this->errorValue);
}
}
}
@ -237,15 +272,16 @@ private:
this->pid = AuAsync::GetCurrentWorkerPId();
}
AuFuture(AuConsumer<Move_t> callback, AuVoidFunc onFailure) : callback(callback), onFailure(onFailure)
AuFuture(AuConsumer<Move_t> callback, ErrorCallback_f onFailure) : callback(callback), onFailure(onFailure)
{
this->pid = AuAsync::GetCurrentWorkerPId();
}
CppFun<T>::B value;
ErrorStore_t errorValue;
AuThreadPrimitives::Mutex mutex;
CompleteCallback_f callback;
AuVoidFunc onFailure;
ErrorCallback_f onFailure;
AuOptionalEx<AuAsync::WorkerPId_t> pid; // todo: make weak?
bool bComplete {};
bool bFailed {};
@ -256,8 +292,8 @@ private:
friend struct AuWaterfall;
};
template<typename T>
using AuSharedFuture = AuSPtr<AuFuture<T>>;
template<typename T, typename Error_t = void>
using AuSharedFuture = AuSPtr<AuFuture<T, Error_t>>;
struct AuWaterfall : AuEnableSharedFromThis<AuWaterfall>
{