134 lines
3.8 KiB
C++
134 lines
3.8 KiB
C++
#ifndef __PROMISE_H__
|
|
#define __PROMISE_H__
|
|
|
|
#include "Private/PromiseHandler.h"
|
|
#include "Private/PromiseResolver.h"
|
|
#include <thread>
|
|
|
|
template <typename T>
|
|
class Promise;
|
|
|
|
template <typename T>
|
|
class PromiseBase {
|
|
friend struct PromiseFulfill<Promise<T>>;
|
|
|
|
public:
|
|
using Type = T;
|
|
template <typename F, typename std::enable_if<ArgsOf<F>::count == 1, int>::type = 0>
|
|
PromiseBase(F callback) : m_d{std::make_shared<PromiseData<T>>()} {
|
|
PromiseResolver<T> resolver{*this};
|
|
try {
|
|
callback(PromiseResolve<T>(resolver));
|
|
} catch (...) {
|
|
resolver.reject(std::current_exception());
|
|
}
|
|
}
|
|
|
|
template <typename F, typename std::enable_if<ArgsOf<F>::count != 1, int>::type = 0>
|
|
PromiseBase(F callback) : m_d{std::make_shared<PromiseData<T>>()} {
|
|
PromiseResolver<T> resolver{*this};
|
|
try {
|
|
callback(PromiseResolve<T>(resolver), PromiseReject<T>(resolver));
|
|
} catch (...) {
|
|
resolver.reject(std::current_exception());
|
|
}
|
|
}
|
|
|
|
PromiseBase(const PromiseBase<T> &other) : m_d{other.m_d} {
|
|
}
|
|
PromiseBase(const Promise<T> &other) : m_d{other.m_d} {
|
|
}
|
|
PromiseBase(PromiseBase<T> &&other) {
|
|
swap(other);
|
|
}
|
|
|
|
void swap(PromiseBase<T> &other) {
|
|
std::swap(m_d, other.m_d);
|
|
}
|
|
|
|
bool isFulfilled() const {
|
|
return m_d->isFulfilled();
|
|
}
|
|
bool isRejected() const {
|
|
return m_d->isRejected();
|
|
}
|
|
bool isPending() const {
|
|
return m_d->isPending();
|
|
}
|
|
|
|
template <typename TFulfilled, typename TRejected>
|
|
typename PromiseHandler<T, TFulfilled>::PromiseType then(const TFulfilled &fulfilled, const TRejected &rejected) const {
|
|
using PromiseType = typename PromiseHandler<T, TFulfilled>::PromiseType;
|
|
|
|
PromiseType next(
|
|
[&](const PromiseResolve<typename PromiseType::Type> &resolve, const PromiseReject<typename PromiseType::Type> &reject) {
|
|
m_d->addHandler(PromiseHandler<T, TFulfilled>::create(fulfilled, resolve, reject));
|
|
m_d->addCatcher(PromiseCatcher<T, TRejected>::create(rejected, resolve, reject));
|
|
});
|
|
|
|
if (!m_d->isPending()) {
|
|
m_d->dispatch();
|
|
}
|
|
|
|
return next;
|
|
}
|
|
|
|
template <typename TFulfilled>
|
|
typename PromiseHandler<T, TFulfilled>::PromiseType then(TFulfilled &&fulfilled) const {
|
|
return then(std::forward<TFulfilled>(fulfilled), nullptr);
|
|
}
|
|
|
|
template <typename TRejected>
|
|
typename PromiseHandler<T, std::nullptr_t>::PromiseType fail(TRejected &&rejected) const {
|
|
return then(nullptr, std::forward<TRejected>(rejected));
|
|
}
|
|
|
|
Promise<T> wait() const {
|
|
while (m_d->isPending()) {
|
|
std::this_thread::yield();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <typename E>
|
|
static Promise<T> reject(E &&error) {
|
|
return Promise<T>{[&](const PromiseResolve<T> &, const PromiseReject<T> &reject) { reject(std::forward<E>(error)); }};
|
|
}
|
|
|
|
protected:
|
|
std::shared_ptr<PromiseData<T>> m_d;
|
|
};
|
|
|
|
template <typename T>
|
|
class Promise : public PromiseBase<T> {
|
|
friend class PromiseResolver<T>;
|
|
|
|
public:
|
|
template <typename F>
|
|
Promise(F &&resolver) : PromiseBase<T>(std::forward<F>(resolver)) {
|
|
}
|
|
|
|
static Promise<T> resolve(const T &value) {
|
|
return Promise<T>{[&](const PromiseResolve<T> &resolve) { resolve(value); }};
|
|
}
|
|
};
|
|
|
|
template <>
|
|
class Promise<void> : public PromiseBase<void> {
|
|
friend class PromiseResolver<void>;
|
|
|
|
public:
|
|
template <typename F>
|
|
Promise(F &&resolver) : PromiseBase<void>(std::forward<F>(resolver)) {
|
|
}
|
|
|
|
public:
|
|
static Promise<void> resolve() {
|
|
return Promise<void>{[](const PromiseResolve<void> &resolve) { resolve(); }};
|
|
}
|
|
|
|
private:
|
|
friend class PromiseBase<void>;
|
|
};
|
|
|
|
#endif // __PROMISE_H__
|