2022-07-19 15:29:20 +00:00
|
|
|
/***
|
|
|
|
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
|
|
|
|
File: IPCPromises.hpp
|
|
|
|
Date: 2022-07-19
|
|
|
|
Author: Reece
|
|
|
|
***/
|
|
|
|
#pragma once
|
|
|
|
|
2022-08-16 07:41:32 +00:00
|
|
|
struct AuNullS
|
|
|
|
{
|
|
|
|
AuUInt8 null;
|
|
|
|
};
|
|
|
|
|
2022-07-19 15:29:20 +00:00
|
|
|
namespace Aurora::Async
|
|
|
|
{
|
|
|
|
struct IPromiseCompleter
|
|
|
|
{
|
|
|
|
virtual void Complete() = 0;
|
|
|
|
virtual void Fail() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct IPromiseComplete
|
|
|
|
{
|
|
|
|
virtual void OnSuccess(void *in) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct IPromiseFailure
|
|
|
|
{
|
|
|
|
virtual void OnFailure(void *in) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct IPromisePtrs
|
|
|
|
{
|
|
|
|
virtual void *GetSuccessPtr() = 0;
|
|
|
|
virtual void *GetErrorPtr() = 0;
|
|
|
|
virtual AuSPtr<void> GetData() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class SuccessValue_t>
|
|
|
|
struct PromiseSuccessTmpl : IPromiseComplete
|
|
|
|
{
|
|
|
|
using OnSuccess_f = AuFunction<void(const AuSPtr<SuccessValue_t> &)>;
|
|
|
|
|
|
|
|
inline virtual void OnSuccess(void *in);
|
|
|
|
|
|
|
|
inline void Init(IPromisePtrs *parent, const OnSuccess_f &onDelegate) noexcept
|
|
|
|
{
|
|
|
|
this->parent_ = parent;
|
|
|
|
this->onSuccess_ = onDelegate;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
IPromisePtrs *parent_;
|
|
|
|
OnSuccess_f onSuccess_;
|
|
|
|
};
|
|
|
|
|
2022-08-16 07:41:32 +00:00
|
|
|
template <class SuccessValue_t, class ErrorValue_t = AuNullS>
|
|
|
|
struct PromiseCallback : IPromiseFailure, IPromiseComplete
|
|
|
|
{
|
|
|
|
inline PromiseCallback()
|
|
|
|
{}
|
|
|
|
|
|
|
|
inline virtual void OnFailure(void *in) override
|
|
|
|
{
|
|
|
|
this->OnFailure(AuReinterpretCast<ErrorValue_t *>(in));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline virtual void OnSuccess(void *in) override
|
|
|
|
{
|
2022-08-21 21:47:02 +00:00
|
|
|
this->OnSuccess(AuReinterpretCast<SuccessValue_t *>(in));
|
2022-08-16 07:41:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void OnFailure(ErrorValue_t *in) = 0;
|
|
|
|
virtual void OnSuccess(SuccessValue_t *in) = 0;
|
|
|
|
};
|
|
|
|
|
2022-08-21 21:47:02 +00:00
|
|
|
template <class SuccessValue_t, class ErrorValue_t = AuNullS>
|
2022-08-16 07:41:32 +00:00
|
|
|
struct PromiseCallbackFunctional : PromiseCallback<SuccessValue_t, ErrorValue_t>, AuEnableSharedFromThis<PromiseCallbackFunctional<SuccessValue_t, ErrorValue_t>>
|
|
|
|
{
|
|
|
|
using OnSuccess_f = AuFunction<void(const AuSPtr<SuccessValue_t> &)>;
|
|
|
|
using OnFailure_f = AuFunction<void(const AuSPtr<ErrorValue_t> &)>;
|
|
|
|
|
|
|
|
inline PromiseCallbackFunctional(OnSuccess_f onSuccess,
|
|
|
|
OnFailure_f onFailure) :
|
|
|
|
onSuccess(onSuccess),
|
|
|
|
onFailure(onFailure)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-08-18 16:19:32 +00:00
|
|
|
inline PromiseCallbackFunctional(OnSuccess_f onSuccess) :
|
|
|
|
onSuccess(onSuccess)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-08-16 07:41:32 +00:00
|
|
|
inline PromiseCallbackFunctional()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void OnFailure(ErrorValue_t *in) override
|
|
|
|
{
|
|
|
|
if (this->onFailure)
|
|
|
|
{
|
|
|
|
if (!in)
|
|
|
|
{
|
|
|
|
this->onFailure({});
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->onFailure(AuSPtr<ErrorValue_t>(AuSharedFromThis(), in));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void OnSuccess(SuccessValue_t *in) override
|
|
|
|
{
|
|
|
|
if (this->onSuccess)
|
|
|
|
{
|
|
|
|
if (!in)
|
|
|
|
{
|
|
|
|
this->onSuccess({});
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->onSuccess(AuSPtr<SuccessValue_t>(AuSharedFromThis(), in));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
OnFailure_f onFailure;
|
|
|
|
OnSuccess_f onSuccess;
|
|
|
|
};
|
|
|
|
|
2022-07-19 15:29:20 +00:00
|
|
|
template <class ErrorValue_t>
|
|
|
|
struct PromiseFailTmpl : IPromiseFailure
|
|
|
|
{
|
|
|
|
using OnFailure_f = AuFunction<void(const AuSPtr<ErrorValue_t> &)>;
|
|
|
|
|
|
|
|
inline virtual void OnFailure(void *in) override;
|
|
|
|
|
|
|
|
inline void Init(IPromisePtrs *parent, const OnFailure_f &onDelegate) noexcept
|
|
|
|
{
|
|
|
|
this->parent_ = parent;
|
|
|
|
this->onFailure_ = onDelegate;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
IPromisePtrs *parent_;
|
|
|
|
OnFailure_f onFailure_;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class SuccessValue_t, class ErrorValue_t>
|
|
|
|
struct Promise;
|
|
|
|
|
|
|
|
|
|
|
|
template <class SuccessValue_t, class ErrorValue_t>
|
|
|
|
struct IPromiseAccessor : IPromiseCompleter
|
|
|
|
{
|
|
|
|
inline virtual AuSPtr<SuccessValue_t> WriteIntoSuccess() = 0;
|
|
|
|
inline virtual AuSPtr<ErrorValue_t> WriteIntoError() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct IPromiseDelegate
|
|
|
|
{
|
|
|
|
virtual void OnPromiseDelegate(const AuSPtr<IPromiseCompleter> &promise) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class SuccessValue_t, class ErrorValue_t>
|
|
|
|
struct PromiseCallTmpl : IPromiseDelegate
|
|
|
|
{
|
|
|
|
using OnDelegate_f = AuFunction<void(const AuSPtr<IPromiseAccessor<SuccessValue_t, ErrorValue_t>> &)>;
|
|
|
|
|
|
|
|
inline virtual void OnPromiseDelegate(const AuSPtr<IPromiseCompleter> &promise) override;
|
|
|
|
|
|
|
|
inline void Init(IPromisePtrs *parent, const OnDelegate_f &onDelegate) noexcept
|
|
|
|
{
|
|
|
|
this->parent_ = parent;
|
|
|
|
this->onDelegate_ = onDelegate;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
IPromisePtrs *parent_;
|
|
|
|
OnDelegate_f onDelegate_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct IPromisePrivateCallbacks
|
|
|
|
{
|
|
|
|
virtual void OnCBTick() = 0;
|
|
|
|
virtual void OnCBDelegate() = 0;
|
|
|
|
virtual void OnCBFailure() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PromiseStartupAdapter : IWorkItemHandler
|
|
|
|
{
|
|
|
|
inline PromiseStartupAdapter(IPromisePrivateCallbacks *parent) noexcept
|
|
|
|
{
|
|
|
|
this->parent_ = parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline virtual void DispatchFrame(IWorkItemHandler::ProcessInfo &info) override
|
|
|
|
{
|
|
|
|
this->parent_->OnCBDelegate();
|
|
|
|
};
|
|
|
|
|
|
|
|
inline virtual void OnFailure() override
|
|
|
|
{
|
|
|
|
SysPushErrorGeneric("Didnt fire initial delegate");
|
|
|
|
this->parent_->OnCBFailure();
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
|
|
|
IPromisePrivateCallbacks *parent_;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PromiseTickAdapter : IWorkItemHandler
|
|
|
|
{
|
|
|
|
inline PromiseTickAdapter(IPromisePrivateCallbacks *parent) noexcept
|
|
|
|
{
|
|
|
|
this->parent_ = parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline virtual void DispatchFrame(IWorkItemHandler::ProcessInfo &info) override
|
|
|
|
{
|
|
|
|
this->parent_->OnCBTick();
|
|
|
|
};
|
|
|
|
|
|
|
|
inline virtual void OnFailure() override
|
|
|
|
{
|
|
|
|
SysPushErrorGeneric("Didnt fire initial delegate");
|
|
|
|
this->parent_->OnCBFailure();
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
|
|
|
IPromisePrivateCallbacks *parent_;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class SuccessValue_t, class ErrorValue_t>
|
|
|
|
struct Promise final : IPromiseAccessor<SuccessValue_t, ErrorValue_t>, AuEnableSharedFromThis<Promise<SuccessValue_t, ErrorValue_t>>, private IPromisePtrs, private IPromisePrivateCallbacks
|
|
|
|
{
|
|
|
|
using This_t = Promise<SuccessValue_t, ErrorValue_t>;
|
|
|
|
|
|
|
|
AU_SAFE_DESTROY(Promise);
|
|
|
|
|
|
|
|
Promise(bool inlineResponse = false, bool allowSync = false);
|
|
|
|
|
|
|
|
using FunctionalCall_t = PromiseCallTmpl<SuccessValue_t, ErrorValue_t>;
|
|
|
|
using FunctionalResponse_t = PromiseSuccessTmpl<SuccessValue_t>;
|
|
|
|
using FunctionalFail_t = PromiseFailTmpl<ErrorValue_t>;
|
2022-08-02 04:52:17 +00:00
|
|
|
using FunctionalResponse_f = typename FunctionalResponse_t::OnSuccess_f;
|
|
|
|
using FunctionalFail_f = typename FunctionalFail_t::OnFailure_f;
|
|
|
|
using FunctionalDelegate_f = typename FunctionalCall_t::OnDelegate_f;
|
2022-07-19 15:29:20 +00:00
|
|
|
|
2022-08-16 07:41:32 +00:00
|
|
|
inline AuSPtr<This_t> SetCallback(const AuSPtr<PromiseCallback<SuccessValue_t, ErrorValue_t>> &callbacks);
|
|
|
|
|
2022-07-19 15:29:20 +00:00
|
|
|
inline AuSPtr<This_t> OnSuccessFunctional(const FunctionalResponse_f &in);
|
|
|
|
inline AuSPtr<This_t> OnSuccessCallback(const AuSPtr<IPromiseComplete> &in);
|
|
|
|
|
|
|
|
inline AuSPtr<This_t> OnFailureFunctional(const FunctionalFail_f &in);
|
|
|
|
inline AuSPtr<This_t> OnFailureCallback(const AuSPtr<IPromiseFailure> &in);
|
|
|
|
|
|
|
|
inline AuSPtr<SuccessValue_t> WriteIntoSuccess() override;
|
|
|
|
inline AuSPtr<ErrorValue_t> WriteIntoError() override;
|
|
|
|
|
|
|
|
inline void Complete() override;
|
|
|
|
inline void Fail() override;
|
|
|
|
|
|
|
|
//inline AuSPtr<IWorkItem> GetBarrier() = 0;
|
|
|
|
|
|
|
|
inline bool WaitBeforeWork(const AuSPtr<IWorkItem> &startingBarrier);
|
|
|
|
|
|
|
|
inline bool BeginWork(WorkerPId_t worker = GetCurrentWorkerPId());
|
|
|
|
inline bool BeginWorkEx(const AuSPtr<IPromiseDelegate> &promise, WorkerPId_t worker = GetCurrentWorkerPId());
|
|
|
|
inline bool BeginWorkFunc(const FunctionalDelegate_f &promise, WorkerPId_t worker = GetCurrentWorkerPId());
|
|
|
|
|
|
|
|
|
|
|
|
inline bool FinalizeWithWork(const AuSPtr<IWorkItem> &sendingFires);
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool bHasBeganWork {};
|
|
|
|
|
|
|
|
AuSPtr<IWorkItem> startingBarrier_;
|
|
|
|
PromiseStartupAdapter startupAdapter;
|
|
|
|
PromiseTickAdapter tickAdapter;
|
|
|
|
|
|
|
|
inline virtual void OnCBTick() override;
|
|
|
|
inline virtual void OnCBDelegate() override;
|
|
|
|
inline virtual void OnCBFailure() override;
|
|
|
|
|
|
|
|
inline void DestroyPrivate();
|
|
|
|
|
|
|
|
inline void *GetSuccessPtr() override;
|
|
|
|
inline void *GetErrorPtr() override;
|
|
|
|
inline AuSPtr<void> GetData() override;
|
|
|
|
|
|
|
|
void DoStartBlocking();
|
|
|
|
void DoFailureBlocking();
|
|
|
|
void DoSuccessBlocking();
|
|
|
|
void DoEndBlocking();
|
|
|
|
|
2022-07-21 22:23:16 +00:00
|
|
|
void DispatchNotifier();
|
|
|
|
|
2022-07-19 15:29:20 +00:00
|
|
|
WorkerPId_t currentThread_;
|
|
|
|
|
|
|
|
SuccessValue_t success;
|
|
|
|
ErrorValue_t error;
|
|
|
|
bool bHasSuccess_ {};
|
|
|
|
bool bHasError_ {};
|
|
|
|
|
|
|
|
bool bHasFiredSuccess_ {};
|
|
|
|
bool bHasFiredError_ {};
|
|
|
|
|
|
|
|
bool bInlineResponse_ {};
|
|
|
|
|
|
|
|
FunctionalResponse_t responseFunctional_;
|
|
|
|
AuSPtr<IPromiseComplete> responseCallback_;
|
|
|
|
|
|
|
|
FunctionalFail_t failureFunctional_;
|
|
|
|
AuSPtr<IPromiseFailure> failureCallback_;
|
|
|
|
|
|
|
|
FunctionalCall_t delegateFunctional_;
|
|
|
|
AuSPtr<IPromiseDelegate> delegateCallback_;
|
|
|
|
|
|
|
|
bool bHasSentError_ {};
|
|
|
|
bool bHasSentSuccess_ {};
|
|
|
|
|
|
|
|
Aurora::Threading::Primitives::SpinLock lock_;
|
|
|
|
|
|
|
|
AuSPtr<IWorkItem> notifier_;
|
|
|
|
|
|
|
|
AuList<AuSPtr<IWorkItem>> startBarriers_;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline Promise<SuccessValue_t, ErrorValue_t>::Promise(bool inlineResponse, bool allowSync) : startupAdapter(this), tickAdapter(this)
|
|
|
|
{
|
|
|
|
this->bInlineResponse_ = inlineResponse;
|
|
|
|
auto pid = GetCurrentWorkerPId();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void Promise<SuccessValue_t, ErrorValue_t>::DestroyPrivate()
|
|
|
|
{
|
|
|
|
if (this->notifier_)
|
|
|
|
{
|
|
|
|
this->notifier_->Cancel();
|
|
|
|
}
|
|
|
|
this->notifier_.reset();
|
|
|
|
|
|
|
|
if (!this->bHasFiredSuccess_ &&
|
|
|
|
!this->bHasFiredError_)
|
|
|
|
{
|
|
|
|
this->bHasFiredError_ = true;
|
|
|
|
DoFailureBlocking();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void Promise<SuccessValue_t, ErrorValue_t>::DoStartBlocking()
|
|
|
|
{}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void Promise<SuccessValue_t, ErrorValue_t>::DoEndBlocking()
|
|
|
|
{
|
|
|
|
this->failureCallback_.reset();
|
|
|
|
this->responseCallback_.reset();
|
|
|
|
this->currentThread_ = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void Promise<SuccessValue_t, ErrorValue_t>::OnCBTick()
|
|
|
|
{
|
|
|
|
if (AuExchange(this->bHasFiredError_, false))
|
|
|
|
{
|
|
|
|
DoFailureBlocking();
|
|
|
|
}
|
|
|
|
else if (AuExchange(this->bHasFiredSuccess_, false))
|
|
|
|
{
|
|
|
|
DoSuccessBlocking();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SysPanic("");
|
|
|
|
}
|
|
|
|
|
|
|
|
this->bHasSentSuccess_ = true;
|
|
|
|
this->bHasSentError_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void Promise<SuccessValue_t, ErrorValue_t>::OnCBDelegate()
|
|
|
|
{
|
|
|
|
//SysAssert(this->currentThread_ == GetCurrentWorkerPId());
|
|
|
|
SysAssert(this->delegateCallback_);
|
|
|
|
AuExchange(this->delegateCallback_, decltype(this->delegateCallback_) {})->OnPromiseDelegate(AuSharedFromThis());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void Promise<SuccessValue_t, ErrorValue_t>::OnCBFailure()
|
|
|
|
{
|
|
|
|
Destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void Promise<SuccessValue_t, ErrorValue_t>::DoFailureBlocking()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
AU_LOCK_GUARD(this->lock_);
|
|
|
|
|
|
|
|
if (AuExchange(this->bHasSentError_, true))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this->DoStartBlocking();
|
|
|
|
|
|
|
|
if (this->failureCallback_)
|
|
|
|
{
|
|
|
|
this->failureCallback_->OnFailure(this->bHasError_ ? &this->error : nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
this->DoEndBlocking();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void Promise<SuccessValue_t, ErrorValue_t>::DoSuccessBlocking()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
AU_LOCK_GUARD(this->lock_);
|
|
|
|
|
|
|
|
if (AuExchange(this->bHasSentError_, true))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (AuExchange(this->bHasSentSuccess_, true))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this->DoStartBlocking();
|
|
|
|
|
|
|
|
if (this->responseCallback_)
|
|
|
|
{
|
|
|
|
this->responseCallback_->OnSuccess(this->bHasSuccess_ ? &this->success : nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
this->DoEndBlocking();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void *Promise<SuccessValue_t, ErrorValue_t>::GetSuccessPtr()
|
|
|
|
{
|
|
|
|
return &this->success;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void *Promise<SuccessValue_t, ErrorValue_t>::GetErrorPtr()
|
|
|
|
{
|
|
|
|
return &this->error;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline AuSPtr<void> Promise<SuccessValue_t, ErrorValue_t>::GetData()
|
|
|
|
{
|
|
|
|
return AuSPtr<void>(AuSharedFromThis());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void Promise<SuccessValue_t, ErrorValue_t>::Complete()
|
|
|
|
{
|
|
|
|
SysAssert(!this->bHasFiredSuccess_);
|
|
|
|
SysAssert(!this->bHasFiredError_);
|
|
|
|
this->bHasFiredSuccess_ = true;
|
|
|
|
|
|
|
|
if (this->bInlineResponse_ &&
|
|
|
|
this->currentThread_ == GetCurrentWorkerPId())
|
|
|
|
{
|
|
|
|
this->DoSuccessBlocking();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-07-21 22:23:16 +00:00
|
|
|
DispatchNotifier();
|
2022-07-19 15:29:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void Promise<SuccessValue_t, ErrorValue_t>::Fail()
|
|
|
|
{
|
|
|
|
SysAssert(!this->bHasFiredSuccess_);
|
|
|
|
this->bHasFiredError_ = true;
|
|
|
|
|
|
|
|
if (this->bInlineResponse_ &&
|
|
|
|
this->currentThread_ == GetCurrentWorkerPId())
|
|
|
|
{
|
|
|
|
this->DoFailureBlocking();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-07-21 22:23:16 +00:00
|
|
|
DispatchNotifier();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void Promise<SuccessValue_t, ErrorValue_t>::DispatchNotifier()
|
|
|
|
{
|
|
|
|
if (!this->notifier_)
|
|
|
|
{
|
2023-12-07 09:20:23 +00:00
|
|
|
this->notifier_ = this->currentThread_.GetPool()->NewWorkItem(this->currentThread_, AuSPtr<IWorkItemHandler>(AuSharedFromThis(), &this->tickAdapter));
|
2022-07-19 15:29:20 +00:00
|
|
|
}
|
2022-07-21 22:23:16 +00:00
|
|
|
|
|
|
|
SysAssert(this->notifier_);
|
|
|
|
this->notifier_->Dispatch();
|
2022-07-19 15:29:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline bool Promise<SuccessValue_t, ErrorValue_t>::WaitBeforeWork(const AuSPtr<IWorkItem> &startingBarrier)
|
|
|
|
{
|
|
|
|
if (!this->startingBarrier_)
|
|
|
|
{
|
2023-12-07 09:20:23 +00:00
|
|
|
this->startingBarrier_ = GetCurrentWorkerPId().GetPool()->NewFence();
|
2022-07-19 15:29:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!this->startingBarrier_)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->startingBarrier_->WaitFor(startingBarrier);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline bool Promise<SuccessValue_t, ErrorValue_t>::BeginWork(WorkerPId_t worker)
|
|
|
|
{
|
|
|
|
this->currentThread_ = GetCurrentWorkerPId();
|
|
|
|
|
2023-12-07 09:20:23 +00:00
|
|
|
SysAssert(worker);
|
2022-07-19 15:29:20 +00:00
|
|
|
|
|
|
|
if (worker == GetCurrentWorkerPId())
|
|
|
|
{
|
|
|
|
if (this->startingBarrier_)
|
|
|
|
{
|
|
|
|
this->startingBarrier_->Dispatch();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->OnCBDelegate();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-12-07 09:20:23 +00:00
|
|
|
auto newItem = worker.GetPool()->NewWorkItem(worker,
|
|
|
|
AuSPtr<IWorkItemHandler>(AuSharedFromThis(), &this->startupAdapter));
|
2022-07-19 15:29:20 +00:00
|
|
|
if (!newItem)
|
|
|
|
{
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this->startingBarrier_)
|
|
|
|
{
|
|
|
|
this->startingBarrier_->Then(newItem);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
newItem->Dispatch();
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline bool Promise<SuccessValue_t, ErrorValue_t>::BeginWorkEx(const AuSPtr<IPromiseDelegate> &promise, WorkerPId_t worker)
|
|
|
|
{
|
|
|
|
this->delegateCallback_ = promise;
|
|
|
|
return BeginWork(worker);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline bool Promise<SuccessValue_t, ErrorValue_t>::BeginWorkFunc(const FunctionalDelegate_f &promise, WorkerPId_t worker)
|
|
|
|
{
|
|
|
|
this->delegateFunctional_.Init(this, promise);
|
|
|
|
return BeginWorkEx(AuUnsafeRaiiToShared(&this->delegateFunctional_), worker);
|
|
|
|
}
|
|
|
|
|
2022-08-16 07:41:32 +00:00
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline AuSPtr<Promise<SuccessValue_t, ErrorValue_t>> Promise<SuccessValue_t, ErrorValue_t>::SetCallback(const AuSPtr<PromiseCallback<SuccessValue_t, ErrorValue_t>> &callbacks)
|
|
|
|
{
|
|
|
|
this->OnSuccessCallback(callbacks);
|
|
|
|
this->OnFailureCallback(callbacks);
|
|
|
|
return AuSPtr<Promise>(AuSharedFromThis());
|
|
|
|
}
|
|
|
|
|
2022-07-19 15:29:20 +00:00
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline AuSPtr<Promise<SuccessValue_t, ErrorValue_t>> Promise<SuccessValue_t, ErrorValue_t>::OnSuccessFunctional(const FunctionalResponse_f &in)
|
|
|
|
{
|
|
|
|
this->responseFunctional_.Init(this, in);
|
|
|
|
return OnSuccessCallback(AuUnsafeRaiiToShared(&this->responseFunctional_));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline AuSPtr<Promise<SuccessValue_t, ErrorValue_t>> Promise<SuccessValue_t, ErrorValue_t>::OnSuccessCallback(const AuSPtr<IPromiseComplete> &in)
|
|
|
|
{
|
|
|
|
bool succeedFast {};
|
|
|
|
{
|
|
|
|
AU_LOCK_GUARD(this->lock_);
|
|
|
|
|
|
|
|
if (this->bHasSentSuccess_)
|
|
|
|
{
|
|
|
|
succeedFast = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->responseCallback_ = in;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (succeedFast)
|
|
|
|
{
|
|
|
|
in->OnSuccess(this->bHasSuccess_ ? &this->success : nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return AuSPtr<Promise>(AuSharedFromThis());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline AuSPtr<Promise<SuccessValue_t, ErrorValue_t>> Promise<SuccessValue_t, ErrorValue_t>::OnFailureFunctional(const FunctionalFail_f &in)
|
|
|
|
{
|
|
|
|
this->failureFunctional_.Init(this, in);
|
|
|
|
return OnFailureCallback(AuUnsafeRaiiToShared(&this->failureFunctional_));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline AuSPtr<Promise<SuccessValue_t, ErrorValue_t>> Promise<SuccessValue_t, ErrorValue_t>::OnFailureCallback(const AuSPtr<IPromiseFailure> &in)
|
|
|
|
{
|
|
|
|
bool failFast {};
|
|
|
|
{
|
|
|
|
AU_LOCK_GUARD(this->lock_);
|
|
|
|
|
|
|
|
if (this->bHasSentError_)
|
|
|
|
{
|
|
|
|
failFast = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->failureCallback_ = in;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (failFast)
|
|
|
|
{
|
2022-07-21 22:23:16 +00:00
|
|
|
in->OnFailure(this->bHasError_ ? &this->error : nullptr);
|
2022-07-19 15:29:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return AuSPtr<Promise>(AuSharedFromThis());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline AuSPtr<SuccessValue_t> Promise<SuccessValue_t, ErrorValue_t>::WriteIntoSuccess()
|
|
|
|
{
|
|
|
|
this->bHasSuccess_ = true;
|
|
|
|
return AuSPtr<SuccessValue_t>(AuSharedFromThis(), &this->success);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline AuSPtr<ErrorValue_t> Promise<SuccessValue_t, ErrorValue_t>::WriteIntoError()
|
|
|
|
{
|
|
|
|
this->bHasError_ = true;
|
2022-09-19 01:34:57 +00:00
|
|
|
return AuSPtr<ErrorValue_t>(AuSharedFromThis(), &this->error);
|
2022-07-19 15:29:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t, class ErrorValue_t>
|
|
|
|
inline void PromiseCallTmpl<SuccessValue_t, ErrorValue_t>::OnPromiseDelegate(const AuSPtr<IPromiseCompleter> &promise)
|
|
|
|
{
|
|
|
|
auto ptr = static_cast<IPromiseAccessor<SuccessValue_t, ErrorValue_t> *>(promise.get());
|
|
|
|
auto sptr = AuSPtr<IPromiseAccessor<SuccessValue_t, ErrorValue_t>>(promise, ptr);
|
|
|
|
|
|
|
|
SysAssert(this->onDelegate_);
|
|
|
|
|
|
|
|
this->onDelegate_(sptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class ErrorValue_t>
|
|
|
|
inline void PromiseFailTmpl<ErrorValue_t>::OnFailure(void *in)
|
|
|
|
{
|
|
|
|
SysAssert(this->onFailure_);
|
|
|
|
|
|
|
|
if (!in)
|
|
|
|
{
|
|
|
|
this->onFailure_({});
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->onFailure_(AuSPtr<ErrorValue_t>(this->parent_->GetData(), (ErrorValue_t *) in));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class SuccessValue_t>
|
|
|
|
inline void PromiseSuccessTmpl<SuccessValue_t>::OnSuccess(void *in)
|
|
|
|
{
|
|
|
|
SysAssert(this->onSuccess_);
|
|
|
|
|
|
|
|
if (!in)
|
|
|
|
{
|
|
|
|
this->onSuccess_({});
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->onSuccess_(AuSPtr<SuccessValue_t>(this->parent_->GetData(), (SuccessValue_t *)in));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
using AuNullPromise = Aurora::Async::Promise<AuNullS, AuNullS>;
|
|
|
|
|
|
|
|
template <class Out_t, class Error_t = AuNullS>
|
|
|
|
using AuPromise = Aurora::Async::Promise<Out_t, Error_t>;
|