Kylin/Universal/Promise.h
2024-09-15 16:15:26 +08:00

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__