Commit 0b87248e authored by octal's avatar octal

async: got rid of code duplication. Removed the Promise<void> specialization...

async: got rid of code duplication. Removed the Promise<void> specialization and specialized the Core instead
parent d39ab557
......@@ -37,19 +37,6 @@ namespace Async {
Pending, Fulfilled, Rejected
};
namespace Private {
struct IgnoreException {
void operator()(std::exception_ptr) const { }
};
struct NoExcept {
void operator()(std::exception_ptr) const { std::terminate(); }
};
}
static constexpr Private::IgnoreException IgnoreException;
static constexpr Private::NoExcept NoExcept;
template<typename T> class Promise;
class PromiseBase {
......@@ -62,116 +49,6 @@ namespace Async {
bool isSettled() const { return isFulfilled() || isRejected(); }
};
namespace Private {
class Core;
class Request {
public:
virtual void resolve(const std::shared_ptr<Private::Core>& core) = 0;
virtual void reject(const std::shared_ptr<Private::Core>& core) = 0;
};
struct Core {
Core(State state)
: state(state)
{ }
State state;
std::exception_ptr exc;
std::vector<std::shared_ptr<Request>> requests;
virtual void* memory() = 0;
virtual bool isVoid() const = 0;
template<typename T, typename... Args>
void construct(Args&&... args) {
if (isVoid())
throw Error("Can not construct a void core");
void *mem = memory();
new (mem) T(std::forward<Args>(args)...);
state = State::Fulfilled;
}
};
}
class Resolver {
public:
Resolver(const std::shared_ptr<Private::Core> &core)
: core_(core)
{ }
template<typename Arg>
bool operator()(Arg&& arg) {
typedef typename std::remove_reference<Arg>::type Type;
if (core_->state != State::Pending)
throw Error("Attempt to resolve a fulfilled promise");
/* In a ideal world, this should be checked at compile-time rather
* than runtime. However, since types are erased, this looks like
* a difficult task
*/
if (core_->isVoid())
throw Error("Attempt to resolve a void promise with arguments");
core_->construct<Type>(std::forward<Arg>(arg));
for (const auto& req: core_->requests) {
req->resolve(core_);
}
return true;
}
bool operator()() {
if (core_->state != State::Pending)
throw Error("Attempt to resolve a fulfilled promise");
if (!core_->isVoid())
throw Error("Attempt ro resolve a non-void promise with no argument");
core_->state = State::Fulfilled;
for (const auto& req: core_->requests) {
req->resolve(core_);
}
return true;
}
private:
std::shared_ptr<Private::Core> core_;
};
class Rejection {
public:
Rejection(const std::shared_ptr<Private::Core>& core)
: core_(core)
{ }
template<typename Exc>
bool operator()(Exc exc) {
if (core_->state != State::Pending)
throw Error("Attempt to reject a fulfilled promise");
core_->exc = std::make_exception_ptr(exc);
core_->state = State::Rejected;
for (const auto& req: core_->requests) {
req->reject(core_);
}
return true;
}
private:
std::shared_ptr<Private::Core> core_;
};
namespace detail {
template<typename Func, typename T>
struct IsCallable {
......@@ -207,96 +84,67 @@ namespace Async {
}
template<typename T>
class Promise : public PromiseBase
{
public:
template<typename U> friend class Promise;
typedef std::function<void (Resolver&, Rejection&)> ResolveFunc;
Promise(ResolveFunc func)
: core_(std::make_shared<CoreT>())
, resolver_(core_)
, rejection_(core_)
{
func(resolver_, rejection_);
}
namespace Private {
Promise(const Promise<T>& other) = delete;
Promise& operator=(const Promise<T>& other) = delete;
struct IgnoreException {
void operator()(std::exception_ptr) const { }
};
Promise(Promise<T>&& other) = default;
Promise& operator=(Promise<T>&& other) = default;
struct NoExcept {
void operator()(std::exception_ptr) const { std::terminate(); }
};
~Promise()
{
}
class Core;
bool isPending() const { return core_->state == State::Pending; }
bool isFulfilled() const { return core_->state == State::Fulfilled; }
bool isRejected() const { return core_->state == State::Rejected; }
class Request {
public:
virtual void resolve(const std::shared_ptr<Core>& core) = 0;
virtual void reject(const std::shared_ptr<Core>& core) = 0;
};
template<typename ResolveFunc, typename RejectFunc>
auto
then(ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc, Continuation type = Continuation::Direct)
-> Promise<
typename detail::RemovePromise<
typename detail::FunctionTrait<ResolveFunc>::ReturnType
>::Type
>
{
static_assert(detail::IsCallable<ResolveFunc, T>::value, "Function is not compatible with underlying promise type");
struct Core {
Core(State state)
: state(state)
{ }
typedef typename detail::RemovePromise<
typename detail::FunctionTrait<ResolveFunc>::ReturnType
>::Type RetType;
State state;
std::exception_ptr exc;
std::vector<std::shared_ptr<Request>> requests;
Promise<RetType> promise;
virtual void* memory() = 0;
// Due to how template argument deduction works on universal references, we need to remove any reference from
// the deduced function type, fun fun fun
typedef typename std::remove_reference<ResolveFunc>::type ResolveFuncType;
typedef typename std::remove_reference<RejectFunc>::type RejectFuncType;
virtual bool isVoid() const = 0;
std::shared_ptr<Private::Request> req;
req.reset(ContinuationFactory<ResolveFuncType>::create(
promise.core_,
std::forward<ResolveFunc>(resolveFunc),
std::forward<RejectFunc>(rejectFunc)));
template<typename T, typename... Args>
void construct(Args&&... args) {
if (isVoid())
throw Error("Can not construct a void core");
if (isFulfilled()) {
req->resolve(core_);
}
else if (isRejected()) {
req->reject(core_);
void *mem = memory();
new (mem) T(std::forward<Args>(args)...);
state = State::Fulfilled;
}
};
core_->requests.push_back(req);
return promise;
}
private:
template<typename U>
struct Core : public Private::Core {
Core()
: Private::Core(State::Pending)
template<typename T>
struct CoreT : public Core {
CoreT()
: Core(State::Pending)
{ }
template<class Other>
struct Rebind {
typedef Core<Other> Type;
typedef CoreT<Other> Type;
};
typedef typename std::aligned_storage<sizeof(U), alignof(U)>::type Storage;
typedef typename std::aligned_storage<sizeof(T), alignof(T)>::type Storage;
Storage storage;
const U& value() const {
const T& value() const {
if (state != State::Fulfilled)
throw Error("Attempted to take the value of a not fulfilled promise");
return *reinterpret_cast<const U*>(&storage);
return *reinterpret_cast<const T*>(&storage);
}
bool isVoid() const { return false; }
......@@ -306,22 +154,27 @@ namespace Async {
}
};
typedef Core<T> CoreT;
template<>
struct CoreT<void> : public Core {
CoreT()
: Core(State::Pending)
{ }
Promise()
: core_(std::make_shared<Core<T>>())
, resolver_(core_)
, rejection_(core_)
{
}
bool isVoid() const { return true; }
struct Continuable : public Private::Request {
void *memory() {
return nullptr;
}
};
template<typename T>
struct Continuable : public Request {
Continuable()
: resolveCount_(0)
, rejectCount_(0)
{ }
void resolve(const std::shared_ptr<Private::Core>& core) {
void resolve(const std::shared_ptr<Core>& core) {
if (resolveCount_ >= 1)
throw Error("Resolve must not be called more than once");
......@@ -329,7 +182,7 @@ namespace Async {
++resolveCount_;
}
void reject(const std::shared_ptr<Private::Core>& core) {
void reject(const std::shared_ptr<Core>& core) {
if (rejectCount_ >= 1)
throw Error("Reject must not be called more than once");
......@@ -337,19 +190,19 @@ namespace Async {
++rejectCount_;
}
std::shared_ptr<CoreT> coreCast(const std::shared_ptr<Private::Core>& core) const {
return std::static_pointer_cast<CoreT>(core);
std::shared_ptr<CoreT<T>> coreCast(const std::shared_ptr<Core>& core) const {
return std::static_pointer_cast<CoreT<T>>(core);
}
virtual void doResolve(const std::shared_ptr<CoreT>& core) const = 0;
virtual void doReject(const std::shared_ptr<CoreT>& core) const = 0;
virtual void doResolve(const std::shared_ptr<CoreT<T>>& core) const = 0;
virtual void doReject(const std::shared_ptr<CoreT<T>>& core) const = 0;
size_t resolveCount_;
size_t rejectCount_;
};
template<typename ResolveFunc, typename RejectFunc>
struct ThenContinuation : public Continuable {
template<typename T, typename ResolveFunc, typename RejectFunc>
struct ThenContinuation : public Continuable<T> {
ThenContinuation(
ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc)
: resolveFunc_(std::forward<ResolveFunc>(resolveFunc))
......@@ -357,22 +210,30 @@ namespace Async {
{
}
void doResolve(const std::shared_ptr<CoreT>& core) const {
resolveFunc_(core->value());
void doResolve(const std::shared_ptr<CoreT<T>>& core) const {
doResolveImpl(core, std::is_void<T>());
}
void doReject(const std::shared_ptr<CoreT>& core) const {
void doReject(const std::shared_ptr<CoreT<T>>& core) const {
rejectFunc_(core->exc);
}
void doResolveImpl(const std::shared_ptr<CoreT<T>>& core, std::true_type /* is_void */) const {
resolveFunc_();
}
void doResolveImpl(const std::shared_ptr<CoreT<T>>& core, std::false_type /* is_void */) const {
resolveFunc_(core->value());
}
ResolveFunc resolveFunc_;
RejectFunc rejectFunc_;
};
template<typename ResolveFunc, typename RejectFunc, typename Return>
struct ThenReturnContinuation : public Continuable {
template<typename T, typename ResolveFunc, typename RejectFunc, typename Return>
struct ThenReturnContinuation : public Continuable<T> {
ThenReturnContinuation(
const std::shared_ptr<Private::Core>& chain,
const std::shared_ptr<Core>& chain,
ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc)
: chain_(chain)
, resolveFunc_(std::forward<ResolveFunc>(resolveFunc))
......@@ -380,24 +241,33 @@ namespace Async {
{
}
void doResolve(const std::shared_ptr<CoreT>& core) const {
auto ret = resolveFunc_(core->value());
chain_->construct<decltype(ret)>(std::move(ret));
void doResolve(const std::shared_ptr<CoreT<T>>& core) const {
doResolveImpl(core, std::is_void<T>());
}
void doReject(const std::shared_ptr<CoreT>& core) const {
void doReject(const std::shared_ptr<CoreT<T>>& core) const {
rejectFunc_(core->exc);
}
std::shared_ptr<Private::Core> chain_;
void doResolveImpl(const std::shared_ptr<CoreT<T>>& core, std::true_type /* is_void */) const {
auto ret = resolveFunc_();
chain_->construct<decltype(ret)>(std::move(ret));
}
void doResolveImpl(const std::shared_ptr<CoreT<T>>& core, std::false_type /* is_void */) const {
auto ret = resolveFunc_(core->value());
chain_->construct<decltype(ret)>(std::move(ret));
}
std::shared_ptr<Core> chain_;
ResolveFunc resolveFunc_;
RejectFunc rejectFunc_;
};
template<typename ResolveFunc, typename RejectFunc>
struct ThenChainContinuation : public Continuable {
template<typename T, typename ResolveFunc, typename RejectFunc>
struct ThenChainContinuation : public Continuable<T> {
ThenChainContinuation(
const std::shared_ptr<Private::Core>& chain,
const std::shared_ptr<Core>& chain,
ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc)
: chain_(chain)
, resolveFunc_(std::forward<ResolveFunc>(resolveFunc))
......@@ -405,8 +275,26 @@ namespace Async {
{
}
void doResolve(const std::shared_ptr<CoreT>& core) const {
void doResolve(const std::shared_ptr<CoreT<T>>& core) const {
doResolveImpl(core, std::is_void<T>());
}
void doReject(const std::shared_ptr<CoreT<T>>& core) const {
rejectFunc_(core->exc);
}
void doResolveImpl(const std::shared_ptr<CoreT<T>>& core, std::true_type /* is_void */) const {
auto promise = resolveFunc_();
finishResolve(promise);
}
void doResolveImpl(const std::shared_ptr<CoreT<T>>& core, std::false_type /* is_void */) const {
auto promise = resolveFunc_(core->value());
finishResolve(promise);
}
template<typename P>
void finishResolve(P& promise) const {
auto chainer = makeChainer(promise);
promise.then(std::move(chainer), [=](std::exception_ptr exc) {
chain_->exc = std::move(exc);
......@@ -414,11 +302,7 @@ namespace Async {
});
}
void doReject(const std::shared_ptr<CoreT>& core) const {
rejectFunc_(core->exc);
}
std::shared_ptr<Private::Core> chain_;
std::shared_ptr<Core> chain_;
ResolveFunc resolveFunc_;
RejectFunc rejectFunc_;
......@@ -432,7 +316,7 @@ namespace Async {
chainCore->construct<PromiseType>(val);
}
std::shared_ptr<Private::Core> chainCore;
std::shared_ptr<Core> chainCore;
};
template<
......@@ -445,103 +329,181 @@ namespace Async {
};
template<typename ResolveFunc>
struct ContinuationFactory : public ContinuationFactory<decltype(&ResolveFunc::operator())> { };
template<typename T, typename ResolveFunc>
struct ContinuationFactory : public ContinuationFactory<T, decltype(&ResolveFunc::operator())> { };
template<typename R, typename Class, typename... Args>
struct ContinuationFactory<R (Class::*)(Args...) const> {
template<typename T, typename R, typename Class, typename... Args>
struct ContinuationFactory<T, R (Class::*)(Args...) const> {
template<typename ResolveFunc, typename RejectFunc>
static Continuable *create(
const std::shared_ptr<Private::Core>& chain,
static Continuable<T>* create(
const std::shared_ptr<Core>& chain,
ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc) {
return new ThenReturnContinuation<ResolveFunc, RejectFunc, R>(
return new ThenReturnContinuation<T, ResolveFunc, RejectFunc, R>(
chain,
std::forward<ResolveFunc>(resolveFunc),
std::forward<RejectFunc>(rejectFunc));
}
};
template<typename Class, typename... Args>
struct ContinuationFactory<void (Class::*)(Args ...) const> {
template<typename T, typename Class, typename... Args>
struct ContinuationFactory<T, void (Class::*)(Args ...) const> {
template<typename ResolveFunc, typename RejectFunc>
static Continuable *create(
static Continuable<T>* create(
const std::shared_ptr<Private::Core>& chain,
ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc) {
return new ThenContinuation<ResolveFunc, RejectFunc>(
return new ThenContinuation<T, ResolveFunc, RejectFunc>(
std::forward<ResolveFunc>(resolveFunc),
std::forward<RejectFunc>(rejectFunc));
}
};
template<typename U, typename Class, typename... Args>
struct ContinuationFactory<Promise<U> (Class::*)(Args...) const> {
template<typename T, typename U, typename Class, typename... Args>
struct ContinuationFactory<T, Promise<U> (Class::*)(Args...) const> {
template<typename ResolveFunc, typename RejectFunc>
static Continuable* create(
static Continuable<T>* create(
const std::shared_ptr<Private::Core>& chain,
ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc) {
return new ThenChainContinuation<ResolveFunc, RejectFunc>(
return new ThenChainContinuation<T, ResolveFunc, RejectFunc>(
chain,
std::forward<ResolveFunc>(resolveFunc),
std::forward<RejectFunc>(rejectFunc));
}
};
std::shared_ptr<CoreT> core_;
Resolver resolver_;
Rejection rejection_;
}
class Resolver {
public:
Resolver(const std::shared_ptr<Private::Core> &core)
: core_(core)
{ }
template<typename Arg>
bool operator()(Arg&& arg) {
typedef typename std::remove_reference<Arg>::type Type;
if (core_->state != State::Pending)
throw Error("Attempt to resolve a fulfilled promise");
/* In a ideal world, this should be checked at compile-time rather
* than runtime. However, since types are erased, this looks like
* a difficult task
*/
if (core_->isVoid())
throw Error("Attempt to resolve a void promise with arguments");
core_->construct<Type>(std::forward<Arg>(arg));
for (const auto& req: core_->requests) {
req->resolve(core_);
}
return true;
}
bool operator()() {
if (core_->state != State::Pending)
throw Error("Attempt to resolve a fulfilled promise");
if (!core_->isVoid())
throw Error("Attempt ro resolve a non-void promise with no argument");
core_->state = State::Fulfilled;
for (const auto& req: core_->requests) {
req->resolve(core_);
}
return true;
}
private:
std::shared_ptr<Private::Core> core_;
};
template<>
class Promise<void> : public PromiseBase
{
class Rejection {
public:
Rejection(const std::shared_ptr<Private::Core>& core)
: core_(core)
{ }
template<typename Exc>
bool operator()(Exc exc) {
if (core_->state != State::Pending)
throw Error("Attempt to reject a fulfilled promise");
core_->exc = std::make_exception_ptr(exc);
core_->state = State::Rejected;
for (const auto& req: core_->requests) {
req->reject(core_);
}
return true;
}
private:
std::shared_ptr<Private::Core> core_;
};
static constexpr Private::IgnoreException IgnoreException;
static constexpr Private::NoExcept NoExcept;
template<typename T>
class Promise : public PromiseBase
{
public:
template<typename U> friend class Promise;
typedef std::function<void (Resolver&, Rejection&)> ResolveFunc;
typedef Private::CoreT<T> Core;
Promise(ResolveFunc func)
: core_(std::make_shared<VoidCore>())
: core_(std::make_shared<Core>())
, resolver_(core_)
, rejection_(core_)
{
func(resolver_, rejection_);
}
bool isPending() const {
return core_->state == State::Pending;
}
Promise(const Promise<T>& other) = delete;
Promise& operator=(const Promise<T>& other) = delete;
bool isFulfilled() const {
return core_->state == State::Fulfilled;
}
Promise(Promise<T>&& other) = default;
Promise& operator=(Promise<T>&& other) = default;
bool isRejected() const {
return core_->state == State::Rejected;
~Promise()
{
}
bool isPending() const { return core_->state == State::Pending; }
bool isFulfilled() const { return core_->state == State::Fulfilled; }
bool isRejected() const { return core_->state == State::Rejected; }
template<typename ResolveFunc, typename RejectFunc>
auto then(ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc)
auto
then(ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc, Continuation type = Continuation::Direct)
-> Promise<
typename detail::RemovePromise<
typename detail::FunctionTrait<ResolveFunc>::ReturnType
>::Type
>
{
static_assert(detail::FunctionTrait<ResolveFunc>::ArgsCount == 0,
"Continuation function of a void promise should not take any argument");
typedef typename detail::RemovePromise<
typename detail::FunctionTrait<ResolveFunc>::ReturnType
>::Type RetType;
thenStaticChecks<ResolveFunc>(std::is_void<T>());
typedef typename detail::RemovePromise<
typename detail::FunctionTrait<ResolveFunc>::ReturnType
>::Type RetType;
Promise<RetType> promise;
Promise<RetType> promise;
// Due to how template argument deduction works on universal references, we need to remove any reference from
// the deduced function type, fun fun fun
typedef typename std::remove_reference<ResolveFunc>::type ResolveFuncType;
typedef typename std::remove_reference<RejectFunc>::type RejectFuncType;
std::shared_ptr<Private::Request> req;
req.reset(ContinuationFactory<ResolveFuncType>::create(
req.reset(Private::ContinuationFactory<T, ResolveFuncType>::create(
promise.core_,
std::forward<ResolveFunc>(resolveFunc),
std::forward<RejectFunc>(rejectFunc)));
......@@ -559,173 +521,26 @@ namespace Async {
}
private:
Promise()
: core_(std::make_shared<VoidCore>())
: core_(std::make_shared<Core>())
, resolver_(core_)
, rejection_(core_)
{ }
struct VoidCore : public Private::Core {
VoidCore() :
Private::Core(State::Pending)
{ }
bool isVoid() const { return true; }
void *memory() { return nullptr; }
};
/* TODO: Crazy code duplication between Promise<T> and its void specialization.
*
* Find a way to get rid of the duplication but still presevering encapsulation
*/
struct Continuable : public Private::Request {
Continuable()
: resolveCount_(0)
, rejectCount_(0)
{ }
void resolve(const std::shared_ptr<Private::Core>& core) {
if (resolveCount_ >= 1)
throw Error("Resolve must not be called more than once");
doResolve(coreCast(core));
++resolveCount_;
}
void reject(const std::shared_ptr<Private::Core>& core) {
if (rejectCount_ >= 1)
throw Error("Reject must not be called more than once");
doReject(coreCast(core));
++rejectCount_;
}
std::shared_ptr<VoidCore> coreCast(const std::shared_ptr<Private::Core>& core) const {
return std::static_pointer_cast<VoidCore>(core);
}
virtual void doResolve(const std::shared_ptr<VoidCore>& core) const = 0;
virtual void doReject(const std::shared_ptr<VoidCore>& core) const = 0;
size_t resolveCount_;
size_t rejectCount_;
};
template<typename ResolveFunc, typename RejectFunc>
struct ThenContinuation : public Continuable {
ThenContinuation(
ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc)
: resolveFunc_(std::forward<ResolveFunc>(resolveFunc))
, rejectFunc_(std::forward<RejectFunc>(rejectFunc))
{
}
void doResolve(const std::shared_ptr<VoidCore>& core) const {
resolveFunc_();
}
void doReject(const std::shared_ptr<VoidCore>& core) const {
rejectFunc_(core->exc);
}
ResolveFunc resolveFunc_;
RejectFunc rejectFunc_;
};
template<typename ResolveFunc, typename RejectFunc, typename Return>
struct ThenReturnContinuation : public Continuable {
ThenReturnContinuation(
const std::shared_ptr<Private::Core>& chain,
ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc)
: chain_(chain)
, resolveFunc_(std::forward<ResolveFunc>(resolveFunc))
, rejectFunc_(std::forward<RejectFunc>(rejectFunc))
{
}
void doResolve(const std::shared_ptr<VoidCore>& core) const {
auto ret = resolveFunc_();
chain_->construct<decltype(ret)>(std::move(ret));
}
void doReject(const std::shared_ptr<VoidCore>& core) const {
rejectFunc_(core->exc);
}
std::shared_ptr<Private::Core> chain_;
ResolveFunc resolveFunc_;
RejectFunc rejectFunc_;
};
template<typename ResolveFunc, typename RejectFunc>
struct ThenChainContinuation : public Continuable {
ThenChainContinuation(
const std::shared_ptr<Private::Core>& chain,
ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc)
: chain_(chain)
, resolveFunc_(std::forward<ResolveFunc>(resolveFunc))
, rejectFunc_(std::forward<RejectFunc>(rejectFunc))
{
}
void doResolve(const std::shared_ptr<VoidCore>& core) const {
auto promise = resolveFunc_();
}
void doReject(const std::shared_ptr<VoidCore>& core) const {
rejectFunc_(core->exc);
}
std::shared_ptr<Private::Core> chain_;
ResolveFunc resolveFunc_;
RejectFunc rejectFunc_;
};
{
}
template<typename ResolveFunc>
struct ContinuationFactory : public ContinuationFactory<decltype(&ResolveFunc::operator())> { };
template<typename R, typename Class, typename... Args>
struct ContinuationFactory<R (Class::*)(Args...) const> {
template<typename ResolveFunc, typename RejectFunc>
static Continuable *create(
const std::shared_ptr<Private::Core>& chain,
ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc) {
return new ThenReturnContinuation<ResolveFunc, RejectFunc, R>(
chain,
std::forward<ResolveFunc>(resolveFunc),
std::forward<RejectFunc>(rejectFunc));
}
};
template<typename Class, typename... Args>
struct ContinuationFactory<void (Class::*)(Args ...) const> {
template<typename ResolveFunc, typename RejectFunc>
static Continuable *create(
const std::shared_ptr<Private::Core>& chain,
ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc) {
return new ThenContinuation<ResolveFunc, RejectFunc>(
std::forward<ResolveFunc>(resolveFunc),
std::forward<RejectFunc>(rejectFunc));
}
};
void thenStaticChecks(std::true_type /* is_void */) {
static_assert(detail::FunctionTrait<ResolveFunc>::ArgsCount == 0,
"Continuation function of a void promise should not take any argument");
}
template<typename U, typename Class, typename... Args>
struct ContinuationFactory<Promise<U> (Class::*)(Args...) const> {
template<typename ResolveFunc, typename RejectFunc>
static Continuable* create(
const std::shared_ptr<Private::Core>& chain,
ResolveFunc&& resolveFunc, RejectFunc&& rejectFunc) {
return new ThenChainContinuation<ResolveFunc, RejectFunc>(
chain,
std::forward<ResolveFunc>(resolveFunc),
std::forward<RejectFunc>(rejectFunc));
}
};
template<typename ResolveFunc>
void thenStaticChecks(std::false_type /* is_void */) {
static_assert(detail::IsCallable<ResolveFunc, T>::value,
"Function is not compatible with underlying promise type");
}
std::shared_ptr<VoidCore> core_;
std::shared_ptr<Core> core_;
Resolver resolver_;
Rejection rejection_;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment