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