diff --git a/include/pistache/async.h b/include/pistache/async.h
index 038ad13cd68006265487ce9cb3137942fa4d2670..bf3524ccc0281b9ec0aa9ab1278591bacae15569 100644
--- a/include/pistache/async.h
+++ b/include/pistache/async.h
@@ -9,1595 +9,1372 @@
 
 #include <pistache/typeid.h>
 
-#include <type_traits>
+#include <atomic>
+#include <condition_variable>
 #include <functional>
 #include <memory>
-#include <atomic>
-#include <vector>
 #include <mutex>
-#include <condition_variable>
 #include <stdexcept>
+#include <type_traits>
 #include <typeinfo>
-
+#include <vector>
 
 namespace Pistache {
 namespace Async {
 
-    class Error : public std::runtime_error {
-    public:
-        explicit Error(const char* what) : std::runtime_error(what) { }
-        explicit Error(const std::string& what) : std::runtime_error(what) { }
-    };
+class Error : public std::runtime_error {
+public:
+  explicit Error(const char *what) : std::runtime_error(what) {}
+  explicit Error(const std::string &what) : std::runtime_error(what) {}
+};
 
-    class BadType : public Error {
-    public:
-        explicit BadType(TypeId id)
-            : Error("Argument type can not be used to resolve the promise "
-                  " (TypeId does not match)")
-            , id_(std::move(id))
-        { }
+class BadType : public Error {
+public:
+  explicit BadType(TypeId id)
+      : Error("Argument type can not be used to resolve the promise "
+              " (TypeId does not match)"),
+        id_(std::move(id)) {}
 
-      TypeId typeId() const {
-          return id_;
-      }
+  TypeId typeId() const { return id_; }
 
-    private:
-        TypeId id_;
-    };
+private:
+  TypeId id_;
+};
 
-    class BadAnyCast : public std::bad_cast {
-    public:
-        const char* what() const noexcept override { return "Bad any cast"; }
-        virtual ~BadAnyCast() { }
-    };
+class BadAnyCast : public std::bad_cast {
+public:
+  const char *what() const noexcept override { return "Bad any cast"; }
+  virtual ~BadAnyCast() {}
+};
 
-    enum class State {
-        Pending, Fulfilled, Rejected
-    };
+enum class State { Pending, Fulfilled, Rejected };
 
-    template<typename T> class Promise;
+template <typename T> class Promise;
 
-    class PromiseBase {
-    public:
-        virtual ~PromiseBase() { }
-        virtual bool isPending() const = 0;
-        virtual bool isFulfilled() const = 0;
-        virtual bool isRejected() const = 0;
+class PromiseBase {
+public:
+  virtual ~PromiseBase() {}
+  virtual bool isPending() const = 0;
+  virtual bool isFulfilled() const = 0;
+  virtual bool isRejected() const = 0;
 
-        bool isSettled() const { return isFulfilled() || isRejected(); }
-    };
+  bool isSettled() const { return isFulfilled() || isRejected(); }
+};
 
-    namespace detail {
-        template<typename Func, typename T>
-        struct IsCallable {
+namespace detail {
+template <typename Func, typename T> struct IsCallable {
 
-            template<typename U>
-            static auto test(U *) -> decltype(std::declval<Func>()(std::declval<U>()), std::true_type());
+  template <typename U>
+  static auto test(U *)
+      -> decltype(std::declval<Func>()(std::declval<U>()), std::true_type());
 
-            template<typename U>
-            static auto test(...) -> std::false_type;
+  template <typename U> static auto test(...) -> std::false_type;
 
-            static constexpr bool value = std::is_same<decltype(test<T>(0)), std::true_type>::value;
-        };
+  static constexpr bool value =
+      std::is_same<decltype(test<T>(0)), std::true_type>::value;
+};
 
-        template<typename Func>
-        struct IsMoveCallable : public IsMoveCallable<decltype(&Func::operator())> { };
+template <typename Func>
+struct IsMoveCallable : public IsMoveCallable<decltype(&Func::operator())> {};
 
-        template<typename R, typename Class, typename Arg>
-        struct IsMoveCallable<R (Class::*)(Arg) const> : public std::is_rvalue_reference<Arg> { };
+template <typename R, typename Class, typename Arg>
+struct IsMoveCallable<R (Class::*)(Arg) const>
+    : public std::is_rvalue_reference<Arg> {};
 
-        template<typename Func, typename Arg>
-        typename std::conditional<
-            IsMoveCallable<Func>::value,
-            Arg&&,
-            const Arg&
-        >::type tryMove(Arg& arg) {
-            return std::move(arg);
-        }
+template <typename Func, typename Arg>
+typename std::conditional<IsMoveCallable<Func>::value, Arg &&,
+                          const Arg &>::type
+tryMove(Arg &arg) {
+  return std::move(arg);
+}
+
+template <typename Func>
+struct FunctionTrait : public FunctionTrait<decltype(&Func::operator())> {};
+
+template <typename R, typename Class, typename... Args>
+struct FunctionTrait<R (Class::*)(Args...) const> {
+  typedef R ReturnType;
+
+  static constexpr size_t ArgsCount = sizeof...(Args);
+};
+
+template <typename R, typename Class, typename... Args>
+struct FunctionTrait<R (Class::*)(Args...)> {
+  typedef R ReturnType;
+
+  static constexpr size_t ArgsCount = sizeof...(Args);
+};
+
+template <typename T> struct RemovePromise { typedef T Type; };
+
+template <typename T> struct RemovePromise<Promise<T>> { typedef T Type; };
+
+template <size_t N, typename... T> struct nth_element;
+
+template <typename Head, typename... Tail>
+struct nth_element<0, Head, Tail...> {
+  typedef Head type;
+};
 
-        template<typename Func>
-        struct FunctionTrait : public FunctionTrait<decltype(&Func::operator())> { };
+template <size_t N, typename Head, typename... Tail>
+struct nth_element<N, Head, Tail...> {
+  typedef typename nth_element<N - 1, Tail...>::type type;
+};
 
-        template<typename R, typename Class, typename... Args>
-        struct FunctionTrait<R (Class::*)(Args...) const> {
-            typedef R ReturnType;
+} // namespace detail
 
-            static constexpr size_t ArgsCount = sizeof...(Args);
-        };
+namespace Private {
 
-        template<typename R, typename Class, typename... Args>
-        struct FunctionTrait<R (Class::*)(Args...)> {
-            typedef R ReturnType;
+struct InternalRethrow {
+  explicit InternalRethrow(std::exception_ptr _exc) : exc(std::move(_exc)) {}
 
-            static constexpr size_t ArgsCount = sizeof...(Args);
-        };
+  std::exception_ptr exc;
+};
 
-        template<typename T>
-        struct RemovePromise {
-            typedef T Type;
-        };
+struct IgnoreException {
+  void operator()(std::exception_ptr) const {}
+};
 
-        template<typename T>
-        struct RemovePromise<Promise<T>> {
-            typedef T Type;
-        };
+struct NoExcept {
+  void operator()(std::exception_ptr) const { std::terminate(); }
+};
 
-        template<size_t N, typename... T> struct nth_element;
+struct Throw {
+  void operator()(std::exception_ptr exc) const {
+    throw InternalRethrow(std::move(exc));
+  }
+};
 
-        template<typename Head, typename... Tail>
-        struct nth_element<0, Head, Tail...> {
-            typedef Head type;
-        };
+struct Core;
 
-        template<size_t N, typename Head, typename... Tail>
-        struct nth_element<N, Head, Tail...> {
-            typedef typename nth_element<N - 1, Tail...>::type type;
-        };
+class Request {
+public:
+  virtual void resolve(const std::shared_ptr<Core> &core) = 0;
+  virtual void reject(const std::shared_ptr<Core> &core) = 0;
+  virtual ~Request() {}
+};
 
+struct Core {
+  Core(State _state, TypeId _id)
+      : allocated(false), state(_state), exc(), mtx(), requests(), id(_id) {}
+
+  bool allocated;
+  std::atomic<State> state;
+  std::exception_ptr exc;
+
+  /*
+   * We need this lock because a Promise might be resolved or rejected from a
+   * thread A while a continuation to the same Promise (Core) might be attached
+   * at the same from a thread B. If that's the case, then we need to serialize
+   * operations so that we avoid a race-condition.
+   *
+   * Since we have a lock, we have a blocking progress guarantee but I don't
+   * expect this to be a major bottleneck as I don't expect major contention on
+   * the lock If it ends up being a bottlenick, try @improving it by
+   * experimenting with a lock-free scheme
+   */
+  std::mutex mtx;
+  std::vector<std::shared_ptr<Request>> requests;
+  TypeId id;
+
+  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");
+
+    if (id != TypeId::of<T>()) {
+      throw BadType(id);
     }
 
-    namespace Private {
-
-        struct InternalRethrow {
-            explicit InternalRethrow(std::exception_ptr _exc)
-                : exc(std::move(_exc))
-            { }
-
-            std::exception_ptr exc;
-        };
-
-        struct IgnoreException {
-            void operator()(std::exception_ptr) const { }
-        };
-
-        struct NoExcept {
-            void operator()(std::exception_ptr) const { std::terminate(); }
-        };
-
-        struct Throw {
-            void operator()(std::exception_ptr exc) const {
-                throw InternalRethrow(std::move(exc));
-            }
-        };
-
-        struct Core;
-
-        class Request {
-        public:
-            virtual void resolve(const std::shared_ptr<Core>& core) = 0;
-            virtual void reject(const std::shared_ptr<Core>& core) = 0;
-            virtual ~Request() {}
-        };
-
-        struct Core {
-            Core(State _state, TypeId _id)
-                : allocated(false)
-                , state(_state)
-                , exc()
-                , mtx()
-                , requests()
-                , id(_id)
-            { }
-
-            bool allocated;
-            std::atomic<State> state;
-            std::exception_ptr exc;
-
-            /*
-             * We need this lock because a Promise might be resolved or rejected from a thread A
-             * while a continuation to the same Promise (Core) might be attached at the same from
-             * a thread B. If that's the case, then we need to serialize operations so that we
-             * avoid a race-condition.
-             *
-             * Since we have a lock, we have a blocking progress guarantee but I don't expect this
-             * to be a major bottleneck as I don't expect major contention on the lock
-             * If it ends up being a bottlenick, try @improving it by experimenting with a lock-free
-             * scheme
-             */
-            std::mutex mtx;
-            std::vector<std::shared_ptr<Request>> requests;
-            TypeId id;
-
-            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");
-
-                if (id != TypeId::of<T>()) {
-                    throw BadType(id);
-                }
-
-                void *mem = memory();
-
-                if (allocated) {
-                    reinterpret_cast<T*>(mem)->~T();
-                    allocated = false;
-                }
-
-                new (mem) T(std::forward<Args>(args)...);
-                allocated = true;
-                state = State::Fulfilled;
-            }
-
-            virtual ~Core() {}
-        };
-
-        template<typename T>
-        struct CoreT : public Core {
-            CoreT()
-                : Core(State::Pending, TypeId::of<T>())
-                , storage()
-            { }
-
-            ~CoreT() {
-                if (allocated) {
-                    reinterpret_cast<T*>(&storage)->~T();
-                    allocated = false;
-                }
-            }
-            
-            template<class Other>
-            struct Rebind {
-                typedef CoreT<Other> Type;
-            };
-
-            T& value() {
-                if (state != State::Fulfilled)
-                    throw Error("Attempted to take the value of a not fulfilled promise");
-
-                return *reinterpret_cast<T*>(&storage);
-            }
-
-            bool isVoid() const override { return false; }
-
-        protected:
-            void *memory() override {
-                return &storage;
-            }
-
-        private:
-            typedef typename std::aligned_storage<sizeof(T), alignof(T)>::type Storage;
-            Storage storage;
-        };
-
-        template<>
-        struct CoreT<void> : public Core {
-            CoreT()
-                : Core(State::Pending, TypeId::of<void>())
-            { }
-
-            bool isVoid() const override { return true; }
-
-        protected:
-            void *memory() override {
-                return nullptr;
-            }
-        };
-
-        template<typename T>
-        struct Continuable : public Request {
-            explicit Continuable(const std::shared_ptr<Core>& chain)
-                : resolveCount_(0)
-                , rejectCount_(0)
-                , chain_(chain)
-            { }
-
-            void resolve(const std::shared_ptr<Core>& core) override {
-                if (resolveCount_ >= 1)
-                  return; //TODO is this the right thing?
-                    //throw Error("Resolve must not be called more than once");
-
-                ++resolveCount_;
-                doResolve(coreCast(core));
-            }
-
-            void reject(const std::shared_ptr<Core>& core) override {
-                if (rejectCount_ >= 1)
-                  return; //TODO is this the right thing?
-                    //throw Error("Reject must not be called more than once");
-
-                ++rejectCount_;
-                try {
-                    doReject(coreCast(core));
-                } catch (const InternalRethrow& e) {
-                    chain_->exc = std::move(e.exc);
-                    chain_->state = State::Rejected;
-                    for (const auto& req: chain_->requests) {
-                        req->reject(chain_);
-                    }
-                }
-
-            }
-
-            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<T>>& core) = 0;
-            virtual void doReject(const std::shared_ptr<CoreT<T>>& core) = 0;
-
-            virtual ~Continuable() { }
-
-            size_t resolveCount_;
-            size_t rejectCount_;
-            std::shared_ptr<Core> chain_;
-        };
-
-        namespace impl {
-
-            template<typename T, typename Resolve, typename Reject, typename U> struct Continuation;
-
-            template<typename T, typename Resolve, typename Reject, typename Res, typename Cls, typename... Args>
-            struct Continuation<T, Resolve, Reject, Res (Cls::*)(Args...) const> : public Continuation<T, Resolve, Reject, Res (Args...)> {
-                typedef Continuation<T, Resolve, Reject, Res (Args...)> Base;
-
-                Continuation(
-                        const std::shared_ptr<Core>& chain,
-                        Resolve resolve,
-                        Reject reject)
-                    : Base(chain, std::move(resolve), std::move(reject))
-                { }
-            };
-
-            template<typename T, typename Resolve, typename Reject, typename Res, typename Cls, typename... Args>
-            struct Continuation<T, Resolve, Reject, Res (Cls::*)(Args...)> : public Continuation<T, Resolve, Reject, Res (Args...)> {
-                typedef Continuation<T, Resolve, Reject, Res (Args...)> Base;
-
-                Continuation(
-                        const std::shared_ptr<Core>& chain,
-                        Resolve resolve,
-                        Reject reject)
-                    : Base(chain, std::move(resolve), std::move(reject))
-                { }
-            };
-
-            // General specialization
-            template<typename T, typename Resolve, typename Reject, typename Res, typename... Args>
-            struct Continuation<T, Resolve, Reject, Res (Args...)> : public Continuable<T> {
-
-                static_assert(sizeof...(Args) == 1,
-                        "A continuation should only take one single argument");
-
-                typedef typename detail::nth_element<0, Args...>::type Arg;
-
-                static_assert(
-                        std::is_same<T, Arg>::value ||
-                        std::is_convertible<T, Arg>::value,
-                        "Incompatible types detected");
-
-                Continuation(
-                        const std::shared_ptr<Core>& chain,
-                        Resolve resolve,
-                        Reject reject)
-                    : Continuable<T>(chain)
-                    , resolve_(resolve)
-                    , reject_(reject)
-                { }
-
-                void doResolve(const std::shared_ptr<CoreT<T>>& core) override {
-                    finishResolve(resolve_(detail::tryMove<Resolve>(core->value())));
-                }
-
-                void doReject(const std::shared_ptr<CoreT<T>>& core) override {
-                    reject_(core->exc);
-                    for (const auto& req: this->chain_->requests) {
-                        req->reject(this->chain_);
-                    }
-                }
-
-                template<typename Ret>
-                void finishResolve(Ret&& ret) const {
-                    typedef typename std::decay<Ret>::type CleanRet;
-                    this->chain_->template construct<CleanRet>(std::forward<Ret>(ret));
-                    for (const auto& req: this->chain_->requests) {
-                        req->resolve(this->chain_);
-                    }
-                }
-
-                Resolve resolve_;
-                Reject reject_;
-            };
-
-            // Specialization for a void-Promise
-            template<typename Resolve, typename Reject, typename Res, typename... Args>
-            struct Continuation<void, Resolve, Reject, Res (Args...)> : public Continuable<void> {
-
-                Continuation(
-                        const std::shared_ptr<Core>& chain,
-                        Resolve resolve,
-                        Reject reject)
-                    : Continuable<void>(chain)
-                    , resolve_(resolve)
-                    , reject_(reject)
-                { }
-
-                static_assert(sizeof...(Args) == 0,
-                        "Can not attach a non-void continuation to a void-Promise");
-
-                void doResolve(const std::shared_ptr<CoreT<void>>& /*core*/) {
-                    finishResolve(resolve_());
-                }
-
-                void doReject(const std::shared_ptr<CoreT<void>>& core) {
-                    reject_(core->exc);
-                    for (const auto& req: this->chain_->requests) {
-                        req->reject(this->chain_);
-                    }
-                }
-
-                template<typename Ret>
-                void finishResolve(Ret&& ret) const {
-                    typedef typename std::remove_reference<Ret>::type CleanRet;
-                    this->chain_->template construct<CleanRet>(std::forward<Ret>(ret));
-                    for (const auto& req: this->chain_->requests) {
-                        req->resolve(this->chain_);
-                    }
-                }
-
-                Resolve resolve_;
-                Reject reject_;
-            };
-
-            // Specialization for a callback returning void
-            template<typename T, typename Resolve, typename Reject, typename... Args>
-            struct Continuation<T, Resolve, Reject, void (Args...)> : public Continuable<T> {
-
-                Continuation(
-                        const std::shared_ptr<Core>& chain,
-                        Resolve resolve,
-                        Reject reject)
-                    : Continuable<T>(chain)
-                    , resolve_(resolve)
-                    , reject_(reject)
-                { }
-
-                static_assert(sizeof...(Args) == 1,
-                        "A continuation should only take one single argument");
-
-                typedef typename detail::nth_element<0, Args...>::type Arg;
-
-                static_assert(
-                        std::is_same<T, Arg>::value ||
-                        std::is_convertible<T, Arg>::value,
-                        "Incompatible types detected");
-
-
-                void doResolve(const std::shared_ptr<CoreT<T>>& core) override {
-                    resolve_(core->value());
-                }
-
-                void doReject(const std::shared_ptr<CoreT<T>>& core) override {
-                    reject_(core->exc);
-                }
-
-                Resolve resolve_;
-                Reject reject_;
-            };
-
-
-            // Specialization for a void-Promise on a callback returning void
-            template<typename Resolve, typename Reject, typename... Args>
-            struct Continuation<void, Resolve, Reject, void (Args...)> : public Continuable<void> {
-
-                Continuation(
-                        const std::shared_ptr<Core>& chain,
-                        Resolve resolve,
-                        Reject reject)
-                    : Continuable<void>(chain)
-                    , resolve_(resolve)
-                    , reject_(reject)
-                { }
-
-                static_assert(sizeof...(Args) == 0,
-                        "Can not attach a non-void continuation to a void-Promise");
-
-                void doResolve(const std::shared_ptr<CoreT<void>>& /*core*/) override {
-                    resolve_();
-                }
-
-                void doReject(const std::shared_ptr<CoreT<void>>& core) override {
-                    reject_(core->exc);
-                }
-
-                Resolve resolve_;
-                Reject reject_;
-
-            };
-
-            // Specialization for a callback returning a Promise
-            template<typename T, typename Resolve, typename Reject, typename U, typename... Args>
-            struct Continuation<T, Resolve, Reject, Promise<U> (Args...)> : public Continuable<T> {
-
-                static_assert(sizeof...(Args) == 1,
-                        "A continuation should only take one single argument");
-
-                typedef typename detail::nth_element<0, Args...>::type Arg;
-
-                static_assert(
-                        std::is_same<T, Arg>::value ||
-                        std::is_convertible<T, Arg>::value,
-                        "Incompatible types detected");
-
-                Continuation(
-                        const std::shared_ptr<Core>& chain,
-                        Resolve resolve,
-                        Reject reject)
-                    : Continuable<T>(chain)
-                    , resolve_(resolve)
-                    , reject_(reject)
-                { }
-
-                void doResolve(const std::shared_ptr<CoreT<T>>& core) override {
-                    auto promise = resolve_(detail::tryMove<Resolve>(core->value()));
-                    finishResolve(promise);
-                }
-
-                void doReject(const std::shared_ptr<CoreT<T>>& core) override {
-                    reject_(core->exc);
-                    for (const auto& req: core->requests) {
-                        req->reject(core);
-                    }
-                }
-
-                template<typename PromiseType>
-                struct Chainer {
-                    explicit Chainer(const std::shared_ptr<Private::Core>& core)
-                        : chainCore(core)
-                    { }
-
-                    void operator()(const PromiseType& val) {
-                        chainCore->construct<PromiseType>(val);
-                        for (const auto& req: chainCore->requests) {
-                            req->resolve(chainCore);
-                        }
-                    }
-
-                    std::shared_ptr<Core> chainCore;
-                };
-
-                template<
-                    typename Promise,
-                    typename Type = typename detail::RemovePromise<Promise>::Type>
-                Chainer<Type>
-                makeChainer(const Promise&) {
-                    return Chainer<Type>(this->chain_);
-                }
-
-                template<typename P>
-                void finishResolve(P& promise) {
-                    auto chainer = makeChainer(promise);
-                    std::weak_ptr<Core> weakPtr = this->chain_;
-                    promise.then(std::move(chainer), [weakPtr](std::exception_ptr exc) {
-                        if (auto core = weakPtr.lock()) {
-                            core->exc = std::move(exc);
-                            core->state = State::Rejected;
-
-                            for (const auto& req: core->requests) {
-                                req->reject(core);
-                            }
-                        }
-                    });
-
-                }
-
-                Resolve resolve_;
-                Reject reject_;
-
-            };
-
-            // Specialization for a void callback returning a Promise
-            template<typename Resolve, typename Reject, typename U, typename... Args>
-            struct Continuation<void, Resolve, Reject, Promise<U> (Args...)> : public Continuable<void> {
-
-                static_assert(sizeof...(Args) == 0,
-                        "Can not attach a non-void continuation to a void-Promise");
-
-                Continuation(
-                        const std::shared_ptr<Core>& chain,
-                        Resolve resolve,
-                        Reject reject)
-                    : Continuable<void>(chain)
-                    , resolve_(resolve)
-                    , reject_(reject)
-                { }
-
-                void doResolve(const std::shared_ptr<CoreT<void>>& /*core*/) {
-                    auto promise = resolve_();
-                    finishResolve(promise);
-                }
-
-                void doReject(const std::shared_ptr<CoreT<void>>& core) {
-                    reject_(core->exc);
-                    for (const auto& req: core->requests) {
-                        req->reject(core);
-                    }
-                }
-
-                template<typename PromiseType, typename Dummy = void>
-                struct Chainer {
-                    explicit Chainer(const std::shared_ptr<Private::Core>& core)
-                        : chainCore(core)
-                    { }
-
-                    void operator()(const PromiseType& val) {
-                        chainCore->construct<PromiseType>(val);
-                        for (const auto& req: chainCore->requests) {
-                            req->resolve(chainCore);
-                        }
-                    }
-
-                    std::shared_ptr<Core> chainCore;
-                };
-
-                template<typename Dummy>
-                struct Chainer<void, Dummy> {
-                    explicit Chainer(const std::shared_ptr<Private::Core>& core)
-                        : chainCore(core)
-                    { }
-
-                    void operator()() {
-                        auto core = this->chain_;
-                        core->state = State::Fulfilled;
-
-                        for (const auto& req: chainCore->requests) {
-                            req->resolve(chainCore);
-                        }
-                    }
-
-                    std::shared_ptr<Core> chainCore;
-                };
-
-                template<
-                    typename Promise,
-                    typename Type = typename detail::RemovePromise<Promise>::Type>
-                Chainer<Type>
-                makeChainer(const Promise&) {
-                    return Chainer<Type>(this->chain_);
-                }
-
-                template<typename P>
-                void finishResolve(P& promise) {
-                    auto chainer = makeChainer(promise);
-                    promise.then(std::move(chainer), [=](std::exception_ptr exc) {
-                        auto core = this->chain_;
-                        core->exc = std::move(exc);
-                        core->state = State::Rejected;
-
-                        for (const auto& req: core->requests) {
-                            req->reject(core);
-                        }
-                    });
-                }
-
-                Resolve resolve_;
-                Reject reject_;
-
-            };
-
-        } // namespace impl
-
-        template<typename T, typename Resolve, typename Reject, typename Sig>
-        struct Continuation : public impl::Continuation<T, Resolve, Reject, decltype(&Sig::operator())>
-        {
-
-            typedef impl::Continuation<T, Resolve, Reject, decltype(&Sig::operator())> Base;
-
-            Continuation(
-                    const std::shared_ptr<Core>& core,
-                    Resolve resolve,
-                    Reject reject)
-                : Base(core, std::move(resolve), std::move(reject))
-            { }
-        };
-
-        template<typename T, typename Resolve, typename Reject, typename Res, typename... Args>
-        struct Continuation<T, Resolve, Reject, Res (*)(Args...)> : public impl::Continuation<T, Resolve, Reject, Res (Args...)>
-        {
-            typedef impl::Continuation<T, Resolve, Reject, Res (Args...)> Base;
-
-            Continuation(
-                    const std::shared_ptr<Core>& core,
-                    Resolve resolve,
-                    Reject reject)
-                : Base(core, std::move(resolve), std::move(reject))
-            { }
-        };
-
-        template<typename T, typename Resolve, typename Reject, typename Res, typename Cls, typename... Args>
-        struct Continuation<T, Resolve, Reject, Res (Cls::*)(Args...)> : public impl::Continuation<T, Resolve, Reject, Res (Args...)>
-        {
-            typedef impl::Continuation<T, Resolve, Reject, Res (Args...)> Base;
-
-            Continuation(
-                    const std::shared_ptr<Core>& core,
-                    Resolve resolve,
-                    Reject reject)
-                : Base(core, std::move(resolve), std::move(reject))
-            { }
-        };
-
-        template<typename T, typename Resolve, typename Reject, typename Res, typename Cls, typename... Args>
-        struct Continuation<T, Resolve, Reject, Res (Cls::*)(Args...) const> : public impl::Continuation<T, Resolve, Reject, Res (Args...)>
-        {
-            typedef impl::Continuation<T, Resolve, Reject, Res (Args...)> Base;
-
-            Continuation(
-                    const std::shared_ptr<Core>& core,
-                    Resolve resolve,
-                    Reject reject)
-                : Base(core, std::move(resolve), std::move(reject))
-            { }
-        };
-
-        template<typename T, typename Resolve, typename Reject, typename Res, typename... Args>
-        struct Continuation<T, Resolve, Reject, std::function<Res (Args...)>> : public impl::Continuation<T, Resolve, Reject, Res (Args...)> {
-            typedef impl::Continuation<T, Resolve, Reject, Res (Args...)> Base;
-
-            Continuation(
-                    const std::shared_ptr<Core>& core,
-                    Resolve resolve,
-                    Reject reject)
-                : Base(core, std::move(resolve), std::move(reject))
-            { }
-        };
+    void *mem = memory();
+
+    if (allocated) {
+      reinterpret_cast<T *>(mem)->~T();
+      allocated = false;
     }
 
-    class Resolver {
-    public:
+    new (mem) T(std::forward<Args>(args)...);
+    allocated = true;
+    state = State::Fulfilled;
+  }
 
-        explicit Resolver(const std::shared_ptr<Private::Core> &core)
-            : core_(core)
-        { }
+  virtual ~Core() {}
+};
 
-        Resolver(const Resolver& other) = delete;
-        Resolver& operator=(const Resolver& other) = delete;
+template <typename T> struct CoreT : public Core {
+  CoreT() : Core(State::Pending, TypeId::of<T>()), storage() {}
 
-        Resolver(Resolver&& other) = default;
-        Resolver& operator=(Resolver&& other) = default;
+  ~CoreT() {
+    if (allocated) {
+      reinterpret_cast<T *>(&storage)->~T();
+      allocated = false;
+    }
+  }
 
-        template<typename Arg>
-        bool operator()(Arg&& arg) const {
-            if (!core_) return false;
+  template <class Other> struct Rebind { typedef CoreT<Other> Type; };
 
-            typedef typename std::remove_reference<Arg>::type Type;
+  T &value() {
+    if (state != State::Fulfilled)
+      throw Error("Attempted to take the value of a not fulfilled promise");
 
-            if (core_->state != State::Pending)
-                throw Error("Attempt to resolve a fulfilled promise");
+    return *reinterpret_cast<T *>(&storage);
+  }
 
-            /* 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");
-            }
+  bool isVoid() const override { return false; }
 
-            std::unique_lock<std::mutex> guard(core_->mtx);
-            core_->construct<Type>(std::forward<Arg>(arg));
+protected:
+  void *memory() override { return &storage; }
 
-            for (const auto& req: core_->requests) {
-                req->resolve(core_);
-            }
+private:
+  typedef typename std::aligned_storage<sizeof(T), alignof(T)>::type Storage;
+  Storage storage;
+};
 
-            return true;
-        }
+template <> struct CoreT<void> : public Core {
+  CoreT() : Core(State::Pending, TypeId::of<void>()) {}
 
-        bool operator()() const {
-            if (!core_) return false;
+  bool isVoid() const override { return true; }
 
-            if (core_->state != State::Pending)
-                throw Error("Attempt to resolve a fulfilled promise");
+protected:
+  void *memory() override { return nullptr; }
+};
 
-            if (!core_->isVoid())
-                throw Error("Attempt ro resolve a non-void promise with no argument");
+template <typename T> struct Continuable : public Request {
+  explicit Continuable(const std::shared_ptr<Core> &chain)
+      : resolveCount_(0), rejectCount_(0), chain_(chain) {}
 
-            std::unique_lock<std::mutex> guard(core_->mtx);
-            core_->state = State::Fulfilled;
-            for (const auto& req: core_->requests) {
-                req->resolve(core_);
-            }
+  void resolve(const std::shared_ptr<Core> &core) override {
+    if (resolveCount_ >= 1)
+      return; // TODO is this the right thing?
+              // throw Error("Resolve must not be called more than once");
 
-            return true;
-        }
+    ++resolveCount_;
+    doResolve(coreCast(core));
+  }
 
-        void clear() {
-            core_ = nullptr;
-        }
+  void reject(const std::shared_ptr<Core> &core) override {
+    if (rejectCount_ >= 1)
+      return; // TODO is this the right thing?
+              // throw Error("Reject must not be called more than once");
 
-        Resolver clone() {
-            return Resolver(core_);
-        }
+    ++rejectCount_;
+    try {
+      doReject(coreCast(core));
+    } catch (const InternalRethrow &e) {
+      chain_->exc = std::move(e.exc);
+      chain_->state = State::Rejected;
+      for (const auto &req : chain_->requests) {
+        req->reject(chain_);
+      }
+    }
+  }
 
-    private:
-        std::shared_ptr<Private::Core> core_;
-    };
+  std::shared_ptr<CoreT<T>> coreCast(const std::shared_ptr<Core> &core) const {
+    return std::static_pointer_cast<CoreT<T>>(core);
+  }
 
-    class Rejection {
-    public:
+  virtual void doResolve(const std::shared_ptr<CoreT<T>> &core) = 0;
+  virtual void doReject(const std::shared_ptr<CoreT<T>> &core) = 0;
 
-        explicit Rejection(const std::shared_ptr<Private::Core>& core)
-            : core_(core)
-        { }
+  virtual ~Continuable() {}
 
-        Rejection(const Rejection& other) = delete;
-        Rejection& operator=(const Rejection& other) = delete;
+  size_t resolveCount_;
+  size_t rejectCount_;
+  std::shared_ptr<Core> chain_;
+};
 
-        Rejection(Rejection&& other) = default;
-        Rejection& operator=(Rejection&& other) = default;
+namespace impl {
 
-        template<typename Exc>
-        bool operator()(Exc exc) const {
-            if (!core_) return false;
+template <typename T, typename Resolve, typename Reject, typename U>
+struct Continuation;
 
-            if (core_->state != State::Pending)
-                throw Error("Attempt to reject a fulfilled promise");
+template <typename T, typename Resolve, typename Reject, typename Res,
+          typename Cls, typename... Args>
+struct Continuation<T, Resolve, Reject, Res (Cls::*)(Args...) const>
+    : public Continuation<T, Resolve, Reject, Res(Args...)> {
+  typedef Continuation<T, Resolve, Reject, Res(Args...)> Base;
 
-            std::unique_lock<std::mutex> guard(core_->mtx);
-            core_->exc = std::make_exception_ptr(exc);
-            core_->state = State::Rejected;
-            for (const auto& req: core_->requests) {
-                req->reject(core_);
-            }
+  Continuation(const std::shared_ptr<Core> &chain, Resolve resolve,
+               Reject reject)
+      : Base(chain, std::move(resolve), std::move(reject)) {}
+};
 
-            return true;
-        }
+template <typename T, typename Resolve, typename Reject, typename Res,
+          typename Cls, typename... Args>
+struct Continuation<T, Resolve, Reject, Res (Cls::*)(Args...)>
+    : public Continuation<T, Resolve, Reject, Res(Args...)> {
+  typedef Continuation<T, Resolve, Reject, Res(Args...)> Base;
 
-        void clear() {
-            core_ = nullptr;
-        }
+  Continuation(const std::shared_ptr<Core> &chain, Resolve resolve,
+               Reject reject)
+      : Base(chain, std::move(resolve), std::move(reject)) {}
+};
 
-        Rejection clone() {
-            return Rejection(core_);
-        }
+// General specialization
+template <typename T, typename Resolve, typename Reject, typename Res,
+          typename... Args>
+struct Continuation<T, Resolve, Reject, Res(Args...)> : public Continuable<T> {
 
-    private:
-        std::shared_ptr<Private::Core> core_;
+  static_assert(sizeof...(Args) == 1,
+                "A continuation should only take one single argument");
 
-    };
+  typedef typename detail::nth_element<0, Args...>::type Arg;
 
-    template<typename T>
-    class Deferred {
-    public:
+  static_assert(std::is_same<T, Arg>::value ||
+                    std::is_convertible<T, Arg>::value,
+                "Incompatible types detected");
 
-        Deferred()
-            : resolver(nullptr)
-            , rejection(nullptr)
-        { }
+  Continuation(const std::shared_ptr<Core> &chain, Resolve resolve,
+               Reject reject)
+      : Continuable<T>(chain), resolve_(resolve), reject_(reject) {}
 
-        Deferred(const Deferred& other) = delete;
-        Deferred& operator=(const Deferred& other) = delete;
+  void doResolve(const std::shared_ptr<CoreT<T>> &core) override {
+    finishResolve(resolve_(detail::tryMove<Resolve>(core->value())));
+  }
 
-        Deferred(Deferred&& other) = default;
-        Deferred& operator=(Deferred&& other) = default;
+  void doReject(const std::shared_ptr<CoreT<T>> &core) override {
+    reject_(core->exc);
+    for (const auto &req : this->chain_->requests) {
+      req->reject(this->chain_);
+    }
+  }
 
-        Deferred(Resolver _resolver, Rejection _reject)
-            : resolver(std::move(_resolver))
-            , rejection(std::move(_reject))
-        { }
+  template <typename Ret> void finishResolve(Ret &&ret) const {
+    typedef typename std::decay<Ret>::type CleanRet;
+    this->chain_->template construct<CleanRet>(std::forward<Ret>(ret));
+    for (const auto &req : this->chain_->requests) {
+      req->resolve(this->chain_);
+    }
+  }
 
-        template<typename U>
-        bool resolve(U&& arg) {
-            typedef typename std::remove_reference<U>::type CleanU;
+  Resolve resolve_;
+  Reject reject_;
+};
 
-            static_assert(std::is_same<T, CleanU>::value || std::is_convertible<U, T>::value,
-                    "Types mismatch");
+// Specialization for a void-Promise
+template <typename Resolve, typename Reject, typename Res, typename... Args>
+struct Continuation<void, Resolve, Reject, Res(Args...)>
+    : public Continuable<void> {
 
-            return resolver(std::forward<U>(arg));
-        }
+  Continuation(const std::shared_ptr<Core> &chain, Resolve resolve,
+               Reject reject)
+      : Continuable<void>(chain), resolve_(resolve), reject_(reject) {}
 
-        template<typename... Args>
-        void emplaceResolve(Args&& ...) {
-        }
+  static_assert(sizeof...(Args) == 0,
+                "Can not attach a non-void continuation to a void-Promise");
 
-        template<typename Exc>
-        bool reject(Exc exc) {
-            return rejection(std::move(exc));
-        }
+  void doResolve(const std::shared_ptr<CoreT<void>> & /*core*/) {
+    finishResolve(resolve_());
+  }
 
-        void clear() {
-            resolver.clear();
-            rejection.clear();
-        }
+  void doReject(const std::shared_ptr<CoreT<void>> &core) {
+    reject_(core->exc);
+    for (const auto &req : this->chain_->requests) {
+      req->reject(this->chain_);
+    }
+  }
 
-    private:
-        Resolver resolver;
-        Rejection rejection;
-    };
+  template <typename Ret> void finishResolve(Ret &&ret) const {
+    typedef typename std::remove_reference<Ret>::type CleanRet;
+    this->chain_->template construct<CleanRet>(std::forward<Ret>(ret));
+    for (const auto &req : this->chain_->requests) {
+      req->resolve(this->chain_);
+    }
+  }
 
-    template<>
-    class Deferred<void> {
-    public:
+  Resolve resolve_;
+  Reject reject_;
+};
 
-        Deferred()
-            : resolver(nullptr)
-            , rejection(nullptr)
-        { }
+// Specialization for a callback returning void
+template <typename T, typename Resolve, typename Reject, typename... Args>
+struct Continuation<T, Resolve, Reject, void(Args...)> : public Continuable<T> {
 
-        Deferred(const Deferred& other) = delete;
-        Deferred& operator=(const Deferred& other) = delete;
+  Continuation(const std::shared_ptr<Core> &chain, Resolve resolve,
+               Reject reject)
+      : Continuable<T>(chain), resolve_(resolve), reject_(reject) {}
 
-        Deferred(Deferred&& other) = default;
-        Deferred& operator=(Deferred&& other) = default;
+  static_assert(sizeof...(Args) == 1,
+                "A continuation should only take one single argument");
 
-        Deferred(Resolver _resolver, Rejection _reject)
-            : resolver(std::move(_resolver))
-            , rejection(std::move(_reject))
-        { }
+  typedef typename detail::nth_element<0, Args...>::type Arg;
 
-        void resolve() {
-            resolver();
-        }
+  static_assert(std::is_same<T, Arg>::value ||
+                    std::is_convertible<T, Arg>::value,
+                "Incompatible types detected");
 
-        template<typename Exc>
-        void reject(Exc _exc) {
-            rejection(std::move(_exc));
-        }
+  void doResolve(const std::shared_ptr<CoreT<T>> &core) override {
+    resolve_(core->value());
+  }
 
-    private:
-        Resolver resolver;
-        Rejection rejection;
-    };
+  void doReject(const std::shared_ptr<CoreT<T>> &core) override {
+    reject_(core->exc);
+  }
 
-    static constexpr Private::IgnoreException IgnoreException{};
-    static constexpr Private::NoExcept NoExcept{};
-    static constexpr Private::Throw Throw{};
-
-    namespace details {
-
-        /*
-         * Note that we could use std::result_of to SFINAE-out and dispatch to the right call
-         * However, gcc 4.7 does not correctly support std::result_of for SFINAE purposes, so we
-         * use a decltype SFINAE-expression instead.
-         *
-         * See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3462.html and
-         * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56283 for reference
-         */
-        template<typename T, typename Func>
-        auto callAsync(Func func, Resolver& resolver, Rejection& rejection)
-            -> decltype(std::declval<Func>()(resolver, rejection), void()) {
-            func(resolver, rejection);
-        }
+  Resolve resolve_;
+  Reject reject_;
+};
 
-        template<typename T, typename Func>
-        auto callAsync(Func func, Resolver& resolver, Rejection& rejection)
-            -> decltype(std::declval<Func>()(Deferred<T>()), void()) {
-            func(Deferred<T>(std::move(resolver), std::move(rejection)));
-        }
-   }
-
-    template<typename T>
-    class Promise : public PromiseBase
-    {
-    public:
-        template<typename U> friend class Promise;
-
-        typedef Private::CoreT<T> Core;
-
-        template<typename Func>
-        explicit Promise(Func func)
-            : core_(std::make_shared<Core>())
-            , resolver_(core_)
-            , rejection_(core_)
-        {
-            details::callAsync<T>(func, resolver_, rejection_);
-        }
+// Specialization for a void-Promise on a callback returning void
+template <typename Resolve, typename Reject, typename... Args>
+struct Continuation<void, Resolve, Reject, void(Args...)>
+    : public Continuable<void> {
 
-        Promise(const Promise<T>& other) = delete;
-        Promise& operator=(const Promise<T>& other) = delete;
+  Continuation(const std::shared_ptr<Core> &chain, Resolve resolve,
+               Reject reject)
+      : Continuable<void>(chain), resolve_(resolve), reject_(reject) {}
 
-        Promise(Promise<T>&& other) = default;
-        Promise& operator=(Promise<T>&& other) = default;
+  static_assert(sizeof...(Args) == 0,
+                "Can not attach a non-void continuation to a void-Promise");
 
-        virtual ~Promise()
-        {
+  void doResolve(const std::shared_ptr<CoreT<void>> & /*core*/) override {
+    resolve_();
+  }
 
-        }
+  void doReject(const std::shared_ptr<CoreT<void>> &core) override {
+    reject_(core->exc);
+  }
 
-        template<typename U>
-        static
-        Promise<T>
-        resolved(U&& value) {
-            static_assert(!std::is_void<T>::value,
-                         "Can not resolve a void promise with parameters");
-            static_assert(std::is_same<T, U>::value || std::is_convertible<U, T>::value,
-                         "Incompatible value type");
-
-            auto core = std::make_shared<Core>();
-            core->template construct<T>(std::forward<U>(value));
-            return Promise<T>(std::move(core));
-        }
+  Resolve resolve_;
+  Reject reject_;
+};
 
-        static
-        Promise<void>
-        resolved() {
-            static_assert(std::is_void<T>::value,
-                         "Resolving a non-void promise requires parameters");
+// Specialization for a callback returning a Promise
+template <typename T, typename Resolve, typename Reject, typename U,
+          typename... Args>
+struct Continuation<T, Resolve, Reject, Promise<U>(Args...)>
+    : public Continuable<T> {
 
-            auto core = std::make_shared<Core>();
-            core->state = State::Fulfilled;
-            return Promise<T>(std::move(core));
-        }
+  static_assert(sizeof...(Args) == 1,
+                "A continuation should only take one single argument");
+
+  typedef typename detail::nth_element<0, Args...>::type Arg;
+
+  static_assert(std::is_same<T, Arg>::value ||
+                    std::is_convertible<T, Arg>::value,
+                "Incompatible types detected");
+
+  Continuation(const std::shared_ptr<Core> &chain, Resolve resolve,
+               Reject reject)
+      : Continuable<T>(chain), resolve_(resolve), reject_(reject) {}
+
+  void doResolve(const std::shared_ptr<CoreT<T>> &core) override {
+    auto promise = resolve_(detail::tryMove<Resolve>(core->value()));
+    finishResolve(promise);
+  }
+
+  void doReject(const std::shared_ptr<CoreT<T>> &core) override {
+    reject_(core->exc);
+    for (const auto &req : core->requests) {
+      req->reject(core);
+    }
+  }
+
+  template <typename PromiseType> struct Chainer {
+    explicit Chainer(const std::shared_ptr<Private::Core> &core)
+        : chainCore(core) {}
+
+    void operator()(const PromiseType &val) {
+      chainCore->construct<PromiseType>(val);
+      for (const auto &req : chainCore->requests) {
+        req->resolve(chainCore);
+      }
+    }
 
-        template<typename Exc>
-        static Promise<T>
-        rejected(Exc exc) {
-            auto core = std::make_shared<Core>();
-            core->exc = std::make_exception_ptr(exc);
-            core->state = State::Rejected;
-            return Promise<T>(std::move(core));
+    std::shared_ptr<Core> chainCore;
+  };
+
+  template <typename Promise,
+            typename Type = typename detail::RemovePromise<Promise>::Type>
+  Chainer<Type> makeChainer(const Promise &) {
+    return Chainer<Type>(this->chain_);
+  }
+
+  template <typename P> void finishResolve(P &promise) {
+    auto chainer = makeChainer(promise);
+    std::weak_ptr<Core> weakPtr = this->chain_;
+    promise.then(std::move(chainer), [weakPtr](std::exception_ptr exc) {
+      if (auto core = weakPtr.lock()) {
+        core->exc = std::move(exc);
+        core->state = State::Rejected;
+
+        for (const auto &req : core->requests) {
+          req->reject(core);
         }
+      }
+    });
+  }
+
+  Resolve resolve_;
+  Reject reject_;
+};
+
+// Specialization for a void callback returning a Promise
+template <typename Resolve, typename Reject, typename U, typename... Args>
+struct Continuation<void, Resolve, Reject, Promise<U>(Args...)>
+    : public Continuable<void> {
+
+  static_assert(sizeof...(Args) == 0,
+                "Can not attach a non-void continuation to a void-Promise");
+
+  Continuation(const std::shared_ptr<Core> &chain, Resolve resolve,
+               Reject reject)
+      : Continuable<void>(chain), resolve_(resolve), reject_(reject) {}
+
+  void doResolve(const std::shared_ptr<CoreT<void>> & /*core*/) {
+    auto promise = resolve_();
+    finishResolve(promise);
+  }
+
+  void doReject(const std::shared_ptr<CoreT<void>> &core) {
+    reject_(core->exc);
+    for (const auto &req : core->requests) {
+      req->reject(core);
+    }
+  }
 
-        bool isPending() const override { return core_->state == State::Pending; }
-        bool isFulfilled() const override { return core_->state == State::Fulfilled; }
-        bool isRejected() const override { return core_->state == State::Rejected; }
+  template <typename PromiseType, typename Dummy = void> struct Chainer {
+    explicit Chainer(const std::shared_ptr<Private::Core> &core)
+        : chainCore(core) {}
 
-        template<typename ResolveFunc, typename RejectFunc>
-        auto
-        then(ResolveFunc resolveFunc, RejectFunc rejectFunc)
-            -> Promise<
-                typename detail::RemovePromise<
-                    typename detail::FunctionTrait<ResolveFunc>::ReturnType
-                >::Type
-              >
-        {
+    void operator()(const PromiseType &val) {
+      chainCore->construct<PromiseType>(val);
+      for (const auto &req : chainCore->requests) {
+        req->resolve(chainCore);
+      }
+    }
 
-            typedef typename detail::RemovePromise<
-                 typename detail::FunctionTrait<ResolveFunc>::ReturnType
-            >::Type RetType;
+    std::shared_ptr<Core> chainCore;
+  };
 
-            Promise<RetType> promise;
+  template <typename Dummy> struct Chainer<void, Dummy> {
+    explicit Chainer(const std::shared_ptr<Private::Core> &core)
+        : chainCore(core) {}
 
-            typedef Private::Continuation<T, ResolveFunc, RejectFunc, ResolveFunc> Continuation;
-            std::shared_ptr<Private::Request> req = std::make_shared<Continuation>(promise.core_, resolveFunc, rejectFunc);
+    void operator()() {
+      auto core = this->chain_;
+      core->state = State::Fulfilled;
 
-            std::unique_lock<std::mutex> guard(core_->mtx);
-            if (isFulfilled()) {
-                req->resolve(core_);
-            }
-            else if (isRejected()) {
-                req->reject(core_);
-            }
+      for (const auto &req : chainCore->requests) {
+        req->resolve(chainCore);
+      }
+    }
 
-            core_->requests.push_back(req);
+    std::shared_ptr<Core> chainCore;
+  };
 
-            return promise;
-        }
+  template <typename Promise,
+            typename Type = typename detail::RemovePromise<Promise>::Type>
+  Chainer<Type> makeChainer(const Promise &) {
+    return Chainer<Type>(this->chain_);
+  }
 
-    private:
-        Promise()
-          : core_(std::make_shared<Core>())
-          , resolver_(core_)
-          , rejection_(core_)
-        {
-        }
+  template <typename P> void finishResolve(P &promise) {
+    auto chainer = makeChainer(promise);
+    promise.then(std::move(chainer), [=](std::exception_ptr exc) {
+      auto core = this->chain_;
+      core->exc = std::move(exc);
+      core->state = State::Rejected;
 
-        explicit Promise(std::shared_ptr<Core>&& core)
-          : core_(core)
-          , resolver_(core_)
-          , rejection_(core_)
-        { }
+      for (const auto &req : core->requests) {
+        req->reject(core);
+      }
+    });
+  }
+
+  Resolve resolve_;
+  Reject reject_;
+};
+
+} // namespace impl
+
+template <typename T, typename Resolve, typename Reject, typename Sig>
+struct Continuation : public impl::Continuation<T, Resolve, Reject,
+                                                decltype(&Sig::operator())> {
+
+  typedef impl::Continuation<T, Resolve, Reject, decltype(&Sig::operator())>
+      Base;
+
+  Continuation(const std::shared_ptr<Core> &core, Resolve resolve,
+               Reject reject)
+      : Base(core, std::move(resolve), std::move(reject)) {}
+};
+
+template <typename T, typename Resolve, typename Reject, typename Res,
+          typename... Args>
+struct Continuation<T, Resolve, Reject, Res (*)(Args...)>
+    : public impl::Continuation<T, Resolve, Reject, Res(Args...)> {
+  typedef impl::Continuation<T, Resolve, Reject, Res(Args...)> Base;
+
+  Continuation(const std::shared_ptr<Core> &core, Resolve resolve,
+               Reject reject)
+      : Base(core, std::move(resolve), std::move(reject)) {}
+};
+
+template <typename T, typename Resolve, typename Reject, typename Res,
+          typename Cls, typename... Args>
+struct Continuation<T, Resolve, Reject, Res (Cls::*)(Args...)>
+    : public impl::Continuation<T, Resolve, Reject, Res(Args...)> {
+  typedef impl::Continuation<T, Resolve, Reject, Res(Args...)> Base;
+
+  Continuation(const std::shared_ptr<Core> &core, Resolve resolve,
+               Reject reject)
+      : Base(core, std::move(resolve), std::move(reject)) {}
+};
+
+template <typename T, typename Resolve, typename Reject, typename Res,
+          typename Cls, typename... Args>
+struct Continuation<T, Resolve, Reject, Res (Cls::*)(Args...) const>
+    : public impl::Continuation<T, Resolve, Reject, Res(Args...)> {
+  typedef impl::Continuation<T, Resolve, Reject, Res(Args...)> Base;
+
+  Continuation(const std::shared_ptr<Core> &core, Resolve resolve,
+               Reject reject)
+      : Base(core, std::move(resolve), std::move(reject)) {}
+};
+
+template <typename T, typename Resolve, typename Reject, typename Res,
+          typename... Args>
+struct Continuation<T, Resolve, Reject, std::function<Res(Args...)>>
+    : public impl::Continuation<T, Resolve, Reject, Res(Args...)> {
+  typedef impl::Continuation<T, Resolve, Reject, Res(Args...)> Base;
+
+  Continuation(const std::shared_ptr<Core> &core, Resolve resolve,
+               Reject reject)
+      : Base(core, std::move(resolve), std::move(reject)) {}
+};
+} // namespace Private
+
+class Resolver {
+public:
+  explicit Resolver(const std::shared_ptr<Private::Core> &core) : core_(core) {}
+
+  Resolver(const Resolver &other) = delete;
+  Resolver &operator=(const Resolver &other) = delete;
+
+  Resolver(Resolver &&other) = default;
+  Resolver &operator=(Resolver &&other) = default;
+
+  template <typename Arg> bool operator()(Arg &&arg) const {
+    if (!core_)
+      return false;
+
+    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");
+    }
 
-        std::shared_ptr<Core> core_;
-        Resolver resolver_;
-        Rejection rejection_;
-    };
+    std::unique_lock<std::mutex> guard(core_->mtx);
+    core_->construct<Type>(std::forward<Arg>(arg));
 
-    template<typename T>
-    class Barrier {
-    public:
-        explicit Barrier(Promise<T>& promise)
-            : promise_(promise) {
-        }
+    for (const auto &req : core_->requests) {
+      req->resolve(core_);
+    }
 
-        void wait() {
-            if (promise_.isFulfilled() || promise_.isRejected()) return;
+    return true;
+  }
 
-            promise_.then([&](const T&) mutable {
-                std::unique_lock<std::mutex> guard(mtx);
-                cv.notify_one();
-            }, [&](std::exception_ptr) mutable {
-                std::unique_lock<std::mutex> guard(mtx);
-                cv.notify_one();
-            });
+  bool operator()() const {
+    if (!core_)
+      return false;
 
-            std::unique_lock<std::mutex> guard(mtx);
-            cv.wait(guard, [&] { return promise_.isFulfilled() || promise_.isRejected(); });
-        }
+    if (core_->state != State::Pending)
+      throw Error("Attempt to resolve a fulfilled promise");
 
-        template<class Rep, class Period>
-        std::cv_status wait_for(const std::chrono::duration<Rep, Period>& period) {
-            if (promise_.isFulfilled() || promise_.isRejected()) return std::cv_status::no_timeout;
+    if (!core_->isVoid())
+      throw Error("Attempt ro resolve a non-void promise with no argument");
 
-            promise_.then([&](const T&) mutable {
-                std::unique_lock<std::mutex> guard(mtx);
-                cv.notify_one();
-            }, [&](std::exception_ptr) mutable {
-                std::unique_lock<std::mutex> guard(mtx);
-                cv.notify_one();
-            });
+    std::unique_lock<std::mutex> guard(core_->mtx);
+    core_->state = State::Fulfilled;
+    for (const auto &req : core_->requests) {
+      req->resolve(core_);
+    }
 
-            std::unique_lock<std::mutex> guard(mtx);
-            return cv.wait_for(guard, period);
-        }
+    return true;
+  }
 
-    private:
-        Promise<T>& promise_;
-        mutable std::mutex mtx;
-        std::condition_variable cv;
-    };
+  void clear() { core_ = nullptr; }
+
+  Resolver clone() { return Resolver(core_); }
+
+private:
+  std::shared_ptr<Private::Core> core_;
+};
 
-    namespace Impl {
-        struct Any;
+class Rejection {
+public:
+  explicit Rejection(const std::shared_ptr<Private::Core> &core)
+      : core_(core) {}
+
+  Rejection(const Rejection &other) = delete;
+  Rejection &operator=(const Rejection &other) = delete;
+
+  Rejection(Rejection &&other) = default;
+  Rejection &operator=(Rejection &&other) = default;
+
+  template <typename Exc> bool operator()(Exc exc) const {
+    if (!core_)
+      return false;
+
+    if (core_->state != State::Pending)
+      throw Error("Attempt to reject a fulfilled promise");
+
+    std::unique_lock<std::mutex> guard(core_->mtx);
+    core_->exc = std::make_exception_ptr(exc);
+    core_->state = State::Rejected;
+    for (const auto &req : core_->requests) {
+      req->reject(core_);
     }
 
-    class Any {
-    public:
-        friend struct Impl::Any;
+    return true;
+  }
 
-        Any(const Any& other) = default;
-        Any& operator=(const Any& other) = default;
+  void clear() { core_ = nullptr; }
 
-        Any(Any&& other) = default;
-        Any& operator=(Any&& other) = default;
+  Rejection clone() { return Rejection(core_); }
 
-        template<typename T>
-        bool is() const {
-            return core_->id == TypeId::of<T>();
-        }
+private:
+  std::shared_ptr<Private::Core> core_;
+};
 
-        template<typename T>
-        T cast() const {
-            if (!is<T>()) throw BadAnyCast();
+template <typename T> class Deferred {
+public:
+  Deferred() : resolver(nullptr), rejection(nullptr) {}
 
-            auto core = std::static_pointer_cast<Private::CoreT<T>>(core_);
-            return core->value();
-        }
+  Deferred(const Deferred &other) = delete;
+  Deferred &operator=(const Deferred &other) = delete;
 
-    private:
-        explicit Any(const std::shared_ptr<Private::Core>& core)
-            : core_(core)
-        { }
-        std::shared_ptr<Private::Core> core_;
+  Deferred(Deferred &&other) = default;
+  Deferred &operator=(Deferred &&other) = default;
 
-    };
+  Deferred(Resolver _resolver, Rejection _reject)
+      : resolver(std::move(_resolver)), rejection(std::move(_reject)) {}
+
+  template <typename U> bool resolve(U &&arg) {
+    typedef typename std::remove_reference<U>::type CleanU;
+
+    static_assert(std::is_same<T, CleanU>::value ||
+                      std::is_convertible<U, T>::value,
+                  "Types mismatch");
+
+    return resolver(std::forward<U>(arg));
+  }
+
+  template <typename... Args> void emplaceResolve(Args &&...) {}
+
+  template <typename Exc> bool reject(Exc exc) {
+    return rejection(std::move(exc));
+  }
+
+  void clear() {
+    resolver.clear();
+    rejection.clear();
+  }
+
+private:
+  Resolver resolver;
+  Rejection rejection;
+};
+
+template <> class Deferred<void> {
+public:
+  Deferred() : resolver(nullptr), rejection(nullptr) {}
+
+  Deferred(const Deferred &other) = delete;
+  Deferred &operator=(const Deferred &other) = delete;
+
+  Deferred(Deferred &&other) = default;
+  Deferred &operator=(Deferred &&other) = default;
 
-    namespace Impl {
+  Deferred(Resolver _resolver, Rejection _reject)
+      : resolver(std::move(_resolver)), rejection(std::move(_reject)) {}
 
-        /* Instead of duplicating the code between whenAll and whenAny functions, the main implementation
-         * is in the When class below and we configure the class with a policy instead,  depending if we
-         * are executing an "all" or "any" operation, how cool is that ?
-         */
-        struct All {
+  void resolve() { resolver(); }
 
-            struct Data {
-                Data(const size_t _total, Resolver _resolver, Rejection _rejection)
-                    : total(_total)
-                    , resolved(0)
-                    , rejected(false)
-                    , mtx()
-                    , resolve(std::move(_resolver))
-                    , reject(std::move(_rejection))
-                { }
+  template <typename Exc> void reject(Exc _exc) { rejection(std::move(_exc)); }
 
-                const size_t total;
-                size_t resolved;
-                bool rejected;
-                std::mutex mtx;
-
-                Resolver resolve;
-                Rejection reject;
-            };
-
-            template<size_t Index, typename T, typename Data>
-            static void resolveT(const T& val, Data& data) {
-                std::lock_guard<std::mutex> guard(data->mtx);
-
-                if (data->rejected) return;
-
-                // @Check thread-safety of std::get ?
-                std::get<Index>(data->results) = val;
-                data->resolved++;
-
-                if (data->resolved == data->total) {
-                    data->resolve(data->results);
-                }
-            }
-
-            template<typename Data>
-            static void resolveVoid(Data& data) {
-                std::lock_guard<std::mutex> guard(data->mtx);
-
-                if (data->rejected) return;
-
-                data->resolved++;
-
-                if (data->resolved == data->total) {
-                    data->resolve(data->results);
-                }
-            }
-
-            template<typename Data>
-            static void reject(std::exception_ptr exc, Data& data) {
-                std::lock_guard<std::mutex> guard(data->mtx);
-
-                data->rejected = true;
-                data->reject(exc);
-            }
-        };
-
-        struct Any {
-
-            struct Data {
-                Data(size_t, Resolver resolver, Rejection rejection)
-                    : done(false)
-                    , mtx()
-                    , resolve(std::move(resolver))
-                    , reject(std::move(rejection))
-                { }
-
-                bool done;
-                std::mutex mtx;
-
-                Resolver resolve;
-                Rejection reject;
-            };
-
-            template<size_t Index, typename T, typename Data>
-            static void resolveT(const T& val, Data& data) {
-                std::lock_guard<std::mutex> guard(data->mtx);
-
-                if (data->done) return;
-
-                // Instead of allocating a new core, ideally we could share the same core as
-                // the relevant promise but we do not have access to the promise here is so meh
-                auto core = std::make_shared<Private::CoreT<T>>();
-                core->template construct<T>(val);
-                data->resolve(Async::Any(core));
-
-                data->done = true;
-            }
-
-            template<typename Data>
-            static void resolveVoid(Data& data) {
-                std::lock_guard<std::mutex> guard(data->mtx);
-
-                if (data->done) return;
-
-                auto core = std::make_shared<Private::CoreT<void>>();
-                data->resolve(Async::Any(core));
-
-                data->done = true;
-            }
-
-            template<typename Data>
-            static void reject(std::exception_ptr exc, Data& data) {
-                std::lock_guard<std::mutex> guard(data->mtx);
-
-                data->done = true;
-                data->reject(exc);
-            }
-        };
-
-        template<typename ContinuationPolicy>
-        struct When {
-            When(Resolver resolver, Rejection rejection)
-                : resolve(std::move(resolver))
-                , reject(std::move(rejection))
-            { }
-
-            template<typename... Args>
-            void operator()(Args&&... args) {
-                whenArgs(std::forward<Args>(args)...);
-            }
-
-        private:
-            template<typename T, size_t Index, typename Data>
-            struct WhenContinuation {
-                explicit WhenContinuation(Data _data)
-                    : data(std::move(_data))
-                { }
-
-                void operator()(const T& val) const {
-                    ContinuationPolicy::template resolveT<Index>(val, data);
-                }
-
-                Data data;
-            };
-
-            template<size_t Index, typename Data>
-            struct WhenContinuation<void, Index, Data> {
-                explicit WhenContinuation(Data _data)
-                    : data(std::move(_data))
-                { }
-
-                void operator()() const {
-                    ContinuationPolicy::resolveVoid(data);
-                }
-
-                Data data;
-
-            };
-
-            template<typename T, size_t Index, typename Data>
-            WhenContinuation<T, Index, Data>
-            makeContinuation(const Data& data) {
-                return WhenContinuation<T, Index, Data>(data);
-            }
-
-            template<size_t Index, typename Data, typename T>
-            void when(const Data& data, Promise<T>& promise) {
-                promise.then(makeContinuation<T, Index>(data), [=](std::exception_ptr ptr) {
-                    ContinuationPolicy::reject(std::move(ptr), data);
-                });
-            }
-
-            template<size_t Index, typename Data, typename T>
-            void when(const Data& data, T&& arg) {
-                typedef typename std::remove_reference<T>::type CleanT;
-                auto promise = Promise<CleanT>::resolved(std::forward<T>(arg));
-                when<Index>(data, promise);
-            }
-
-            template<typename... Args>
-            void whenArgs(Args&& ...args) {
-                typedef std::tuple<
-                            typename detail::RemovePromise<
-                                typename std::remove_reference<Args>::type
-                            >::Type...
-                        > Results;
-                /* We need to keep the results alive until the last promise
-                 * finishes its execution
-                 */
-
-                /* See the trick here ? Basically, we only have access to the real type of the results
-                 * in this function. The policy classes do not have access to the full type (std::tuple),
-                 * but, instead, take a generic template data type as a parameter. They only need to know
-                 * that results is a tuple, they do not need to know the real type of the results.
-                 *
-                 * This is some sort of compile-time template type-erasing, hue
-                 */
-                struct Data : public ContinuationPolicy::Data {
-                    Data(size_t total, Resolver resolver, Rejection rejection)
-                        : ContinuationPolicy::Data(total, std::move(resolver), std::move(rejection))
-                    { }
-
-                    Results results;
-                };
-
-                auto data = std::make_shared<Data>(sizeof...(Args), std::move(resolve), std::move(reject));
-                whenArgs<0>(data, std::forward<Args>(args)...);
-            }
-
-            template<size_t Index, typename Data, typename Head,  typename... Rest>
-            void whenArgs(const Data& data, Head&& head, Rest&& ...rest) {
-                when<Index>(data, std::forward<Head>(head));
-                whenArgs<Index + 1>(data, std::forward<Rest>(rest)...);
-            }
-
-            template<size_t Index, typename Data, typename Head>
-            void whenArgs(const Data& data, Head&& head) {
-                when<Index>(data, std::forward<Head>(head));
-            }
-
-            Resolver resolve;
-            Rejection reject;
-        };
-
-        template<
-                 typename T,
-                 typename Results
-                >
-        struct WhenAllRange
-        {
-            WhenAllRange(Resolver _resolve, Rejection _reject)
-                : resolve(std::move(_resolve))
-                , reject(std::move(_reject))
-            { }
-
-            template<typename Iterator>
-            void operator()(Iterator first, Iterator last)
-            {
-                auto data = std::make_shared<DataT<T>>(
-                   static_cast<size_t>(std::distance(first, last)),
-                   std::move(resolve),
-                   std::move(reject)
-                );
-
-                size_t index = 0;
-                for (auto it = first; it != last; ++it) {
-
-                    WhenContinuation<T> cont(data, index);
-
-                    it->then(std::move(cont), [=](std::exception_ptr ptr) {
-                        std::lock_guard<std::mutex> guard(data->mtx);
-
-                        if (data->rejected) return;
-
-                        data->rejected = true;
-                        data->reject(std::move(ptr));
-                    });
-
-                    ++index;
-                }
-            }
-
-        private:
-            struct Data
-            {
-                Data(size_t _total, Resolver _resolver, Rejection _rejection)
-                    : total(_total)
-                    , resolved(0)
-                    , rejected(false)
-                    , mtx()
-                    , resolve(std::move(_resolver))
-                    , reject(std::move(_rejection))
-                { }
-
-                const size_t total;
-                size_t resolved;
-                bool rejected;
-                std::mutex mtx;
-
-                Resolver resolve;
-                Rejection reject;
-            };
-
-            /* Ok so apparently I can not fully specialize a template structure
-             * here, so you know what, compiler ? Take that Dummy type and leave
-             * me alone
-             */
-            template<typename ValueType, typename Dummy = void> struct DataT : public Data {
-                DataT(size_t total, Resolver resolver, Rejection rejection)
-                    : Data(total, std::move(resolver), std::move(rejection))
-                {
-                    results.resize(total);
-                }
-
-                Results results;
-            };
-
-            /* For a vector of void promises, we do not have any results, that's
-             * why we need a distinct specialization for the void case
-             */
-            template<typename Dummy> struct DataT<void, Dummy> : public Data {
-                DataT(size_t total, Resolver resolver, Rejection rejection)
-                    : Data(total, std::move(resolver), std::move(rejection))
-                {
-                }
-            };
-
-            template<typename ValueType, typename Dummy = void>
-            struct WhenContinuation
-            {
-                using D = std::shared_ptr<DataT<ValueType>>;
-
-                WhenContinuation(const D& _data, size_t _index)
-                    : data(_data)
-                    , index(_index)
-                { }
-
-                void operator()(const ValueType& val) const
-                {
-                    std::lock_guard<std::mutex> guard(data->mtx);
-
-                    if (data->rejected) return;
-
-                    data->results[index] = val;
-                    data->resolved++;
-                    if (data->resolved == data->total)
-                    {
-                        data->resolve(data->results);
-                    }
-                }
-
-                D data;
-                size_t index;
-            };
-
-            template<typename Dummy>
-            struct WhenContinuation<void, Dummy>
-            {
-                using D = std::shared_ptr<DataT<void>>;
-
-                WhenContinuation(const D& _data, size_t)
-                    : data(_data)
-                { }
-
-                void operator()() const
-                {
-                    std::lock_guard<std::mutex> guard(data->mtx);
-
-                    if (data->rejected) return;
-
-                    data->resolved++;
-                    if (data->resolved == data->total)
-                    {
-                        data->resolve();
-                    }
-                }
-
-                D data;
-            };
-
-            Resolver resolve;
-            Rejection reject;
-        };
+private:
+  Resolver resolver;
+  Rejection rejection;
+};
 
+static constexpr Private::IgnoreException IgnoreException{};
+static constexpr Private::NoExcept NoExcept{};
+static constexpr Private::Throw Throw{};
+
+namespace details {
+
+/*
+ * Note that we could use std::result_of to SFINAE-out and dispatch to the right
+ * call However, gcc 4.7 does not correctly support std::result_of for SFINAE
+ * purposes, so we use a decltype SFINAE-expression instead.
+ *
+ * See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3462.html and
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56283 for reference
+ */
+template <typename T, typename Func>
+auto callAsync(Func func, Resolver &resolver, Rejection &rejection)
+    -> decltype(std::declval<Func>()(resolver, rejection), void()) {
+  func(resolver, rejection);
+}
+
+template <typename T, typename Func>
+auto callAsync(Func func, Resolver &resolver, Rejection &rejection)
+    -> decltype(std::declval<Func>()(Deferred<T>()), void()) {
+  func(Deferred<T>(std::move(resolver), std::move(rejection)));
+}
+} // namespace details
+
+template <typename T> class Promise : public PromiseBase {
+public:
+  template <typename U> friend class Promise;
+
+  typedef Private::CoreT<T> Core;
+
+  template <typename Func>
+  explicit Promise(Func func)
+      : core_(std::make_shared<Core>()), resolver_(core_), rejection_(core_) {
+    details::callAsync<T>(func, resolver_, rejection_);
+  }
+
+  Promise(const Promise<T> &other) = delete;
+  Promise &operator=(const Promise<T> &other) = delete;
+
+  Promise(Promise<T> &&other) = default;
+  Promise &operator=(Promise<T> &&other) = default;
+
+  virtual ~Promise() {}
+
+  template <typename U> static Promise<T> resolved(U &&value) {
+    static_assert(!std::is_void<T>::value,
+                  "Can not resolve a void promise with parameters");
+    static_assert(std::is_same<T, U>::value || std::is_convertible<U, T>::value,
+                  "Incompatible value type");
+
+    auto core = std::make_shared<Core>();
+    core->template construct<T>(std::forward<U>(value));
+    return Promise<T>(std::move(core));
+  }
+
+  static Promise<void> resolved() {
+    static_assert(std::is_void<T>::value,
+                  "Resolving a non-void promise requires parameters");
+
+    auto core = std::make_shared<Core>();
+    core->state = State::Fulfilled;
+    return Promise<T>(std::move(core));
+  }
+
+  template <typename Exc> static Promise<T> rejected(Exc exc) {
+    auto core = std::make_shared<Core>();
+    core->exc = std::make_exception_ptr(exc);
+    core->state = State::Rejected;
+    return Promise<T>(std::move(core));
+  }
+
+  bool isPending() const override { return core_->state == State::Pending; }
+  bool isFulfilled() const override { return core_->state == State::Fulfilled; }
+  bool isRejected() const override { return core_->state == State::Rejected; }
+
+  template <typename ResolveFunc, typename RejectFunc>
+  auto then(ResolveFunc resolveFunc, RejectFunc rejectFunc)
+      -> Promise<typename detail::RemovePromise<
+          typename detail::FunctionTrait<ResolveFunc>::ReturnType>::Type> {
+
+    typedef typename detail::RemovePromise<
+        typename detail::FunctionTrait<ResolveFunc>::ReturnType>::Type RetType;
+
+    Promise<RetType> promise;
+
+    typedef Private::Continuation<T, ResolveFunc, RejectFunc, ResolveFunc>
+        Continuation;
+    std::shared_ptr<Private::Request> req =
+        std::make_shared<Continuation>(promise.core_, resolveFunc, rejectFunc);
+
+    std::unique_lock<std::mutex> guard(core_->mtx);
+    if (isFulfilled()) {
+      req->resolve(core_);
+    } else if (isRejected()) {
+      req->reject(core_);
     }
 
-    template<
-        typename... Args,
-        typename Results =
-        std::tuple<
-              typename detail::RemovePromise<
-                  typename std::remove_reference<Args>::type
-              >::Type...
-        >
-    >
-    Promise<Results> whenAll(Args&& ...args) {
-        // As ugly as it looks, this is needed to bypass a bug of gcc < 4.9
-        // whereby template parameters pack inside a lambda expression are not
-        // captured correctly and can not be expanded inside the lambda.
-        Resolver* resolve;
-        Rejection* reject;
-
-        Promise<Results> promise([&](Resolver& resolver, Rejection& rejection) {
-            resolve = &resolver;
-            reject = &rejection;
+    core_->requests.push_back(req);
+
+    return promise;
+  }
+
+private:
+  Promise()
+      : core_(std::make_shared<Core>()), resolver_(core_), rejection_(core_) {}
+
+  explicit Promise(std::shared_ptr<Core> &&core)
+      : core_(core), resolver_(core_), rejection_(core_) {}
+
+  std::shared_ptr<Core> core_;
+  Resolver resolver_;
+  Rejection rejection_;
+};
+
+template <typename T> class Barrier {
+public:
+  explicit Barrier(Promise<T> &promise) : promise_(promise) {}
+
+  void wait() {
+    if (promise_.isFulfilled() || promise_.isRejected())
+      return;
+
+    promise_.then(
+        [&](const T &) mutable {
+          std::unique_lock<std::mutex> guard(mtx);
+          cv.notify_one();
+        },
+        [&](std::exception_ptr) mutable {
+          std::unique_lock<std::mutex> guard(mtx);
+          cv.notify_one();
+        });
+
+    std::unique_lock<std::mutex> guard(mtx);
+    cv.wait(guard,
+            [&] { return promise_.isFulfilled() || promise_.isRejected(); });
+  }
+
+  template <class Rep, class Period>
+  std::cv_status wait_for(const std::chrono::duration<Rep, Period> &period) {
+    if (promise_.isFulfilled() || promise_.isRejected())
+      return std::cv_status::no_timeout;
+
+    promise_.then(
+        [&](const T &) mutable {
+          std::unique_lock<std::mutex> guard(mtx);
+          cv.notify_one();
+        },
+        [&](std::exception_ptr) mutable {
+          std::unique_lock<std::mutex> guard(mtx);
+          cv.notify_one();
         });
 
-        Impl::When<Impl::All> impl(std::move(*resolve), std::move(*reject));
-        // So we capture everything we need inside the lambda and then call the
-        // implementation and expand the parameters pack here
-        impl(std::forward<Args>(args)...);
+    std::unique_lock<std::mutex> guard(mtx);
+    return cv.wait_for(guard, period);
+  }
+
+private:
+  Promise<T> &promise_;
+  mutable std::mutex mtx;
+  std::condition_variable cv;
+};
+
+namespace Impl {
+struct Any;
+}
+
+class Any {
+public:
+  friend struct Impl::Any;
+
+  Any(const Any &other) = default;
+  Any &operator=(const Any &other) = default;
+
+  Any(Any &&other) = default;
+  Any &operator=(Any &&other) = default;
+
+  template <typename T> bool is() const { return core_->id == TypeId::of<T>(); }
+
+  template <typename T> T cast() const {
+    if (!is<T>())
+      throw BadAnyCast();
+
+    auto core = std::static_pointer_cast<Private::CoreT<T>>(core_);
+    return core->value();
+  }
+
+private:
+  explicit Any(const std::shared_ptr<Private::Core> &core) : core_(core) {}
+  std::shared_ptr<Private::Core> core_;
+};
 
-        return promise;
+namespace Impl {
+
+/* Instead of duplicating the code between whenAll and whenAny functions, the
+ * main implementation is in the When class below and we configure the class
+ * with a policy instead,  depending if we are executing an "all" or "any"
+ * operation, how cool is that ?
+ */
+struct All {
+
+  struct Data {
+    Data(const size_t _total, Resolver _resolver, Rejection _rejection)
+        : total(_total), resolved(0), rejected(false), mtx(),
+          resolve(std::move(_resolver)), reject(std::move(_rejection)) {}
+
+    const size_t total;
+    size_t resolved;
+    bool rejected;
+    std::mutex mtx;
+
+    Resolver resolve;
+    Rejection reject;
+  };
+
+  template <size_t Index, typename T, typename Data>
+  static void resolveT(const T &val, Data &data) {
+    std::lock_guard<std::mutex> guard(data->mtx);
+
+    if (data->rejected)
+      return;
+
+    // @Check thread-safety of std::get ?
+    std::get<Index>(data->results) = val;
+    data->resolved++;
+
+    if (data->resolved == data->total) {
+      data->resolve(data->results);
     }
+  }
 
-    template<typename... Args>
-    Promise<Any> whenAny(Args&& ...args) {
-        // Same trick as above;
-        Resolver* resolve;
-        Rejection* reject;
+  template <typename Data> static void resolveVoid(Data &data) {
+    std::lock_guard<std::mutex> guard(data->mtx);
 
-        Promise<Any> promise([&](Resolver& resolver, Rejection& rejection) {
-            resolve = &resolver;
-            reject = &rejection;
-        });
+    if (data->rejected)
+      return;
 
-        Impl::When<Impl::Any> impl(std::move(*resolve), std::move(*reject));
-        impl(std::forward<Args>(args)...);
-        return promise;
+    data->resolved++;
+
+    if (data->resolved == data->total) {
+      data->resolve(data->results);
     }
+  }
 
-    template<
-        typename Iterator,
-        typename ValueType
-            = typename detail::RemovePromise<
-                  typename std::iterator_traits<Iterator>::value_type
-              >::Type,
-        typename Results
-            = typename std::conditional<
-                        std::is_same<void, ValueType>::value,
-                    void, std::vector<ValueType>
-              >::type
-    >
-    Promise<Results> whenAll(Iterator first, Iterator last) {
-        /* @Security, assert that last >= first */
+  template <typename Data>
+  static void reject(std::exception_ptr exc, Data &data) {
+    std::lock_guard<std::mutex> guard(data->mtx);
 
-        return Promise<Results>([=](Resolver& resolve, Rejection& rejection) {
+    data->rejected = true;
+    data->reject(exc);
+  }
+};
 
-            Impl::WhenAllRange<ValueType, Results> impl(
-                std::move(resolve), std::move(rejection));
+struct Any {
 
-            impl(first, last);
+  struct Data {
+    Data(size_t, Resolver resolver, Rejection rejection)
+        : done(false), mtx(), resolve(std::move(resolver)),
+          reject(std::move(rejection)) {}
 
-        });
+    bool done;
+    std::mutex mtx;
+
+    Resolver resolve;
+    Rejection reject;
+  };
+
+  template <size_t Index, typename T, typename Data>
+  static void resolveT(const T &val, Data &data) {
+    std::lock_guard<std::mutex> guard(data->mtx);
+
+    if (data->done)
+      return;
+
+    // Instead of allocating a new core, ideally we could share the same core as
+    // the relevant promise but we do not have access to the promise here is so
+    // meh
+    auto core = std::make_shared<Private::CoreT<T>>();
+    core->template construct<T>(val);
+    data->resolve(Async::Any(core));
+
+    data->done = true;
+  }
+
+  template <typename Data> static void resolveVoid(Data &data) {
+    std::lock_guard<std::mutex> guard(data->mtx);
+
+    if (data->done)
+      return;
+
+    auto core = std::make_shared<Private::CoreT<void>>();
+    data->resolve(Async::Any(core));
+
+    data->done = true;
+  }
+
+  template <typename Data>
+  static void reject(std::exception_ptr exc, Data &data) {
+    std::lock_guard<std::mutex> guard(data->mtx);
+
+    data->done = true;
+    data->reject(exc);
+  }
+};
+
+template <typename ContinuationPolicy> struct When {
+  When(Resolver resolver, Rejection rejection)
+      : resolve(std::move(resolver)), reject(std::move(rejection)) {}
+
+  template <typename... Args> void operator()(Args &&... args) {
+    whenArgs(std::forward<Args>(args)...);
+  }
+
+private:
+  template <typename T, size_t Index, typename Data> struct WhenContinuation {
+    explicit WhenContinuation(Data _data) : data(std::move(_data)) {}
+
+    void operator()(const T &val) const {
+      ContinuationPolicy::template resolveT<Index>(val, data);
+    }
+
+    Data data;
+  };
+
+  template <size_t Index, typename Data>
+  struct WhenContinuation<void, Index, Data> {
+    explicit WhenContinuation(Data _data) : data(std::move(_data)) {}
+
+    void operator()() const { ContinuationPolicy::resolveVoid(data); }
+
+    Data data;
+  };
+
+  template <typename T, size_t Index, typename Data>
+  WhenContinuation<T, Index, Data> makeContinuation(const Data &data) {
+    return WhenContinuation<T, Index, Data>(data);
+  }
+
+  template <size_t Index, typename Data, typename T>
+  void when(const Data &data, Promise<T> &promise) {
+    promise.then(makeContinuation<T, Index>(data), [=](std::exception_ptr ptr) {
+      ContinuationPolicy::reject(std::move(ptr), data);
+    });
+  }
+
+  template <size_t Index, typename Data, typename T>
+  void when(const Data &data, T &&arg) {
+    typedef typename std::remove_reference<T>::type CleanT;
+    auto promise = Promise<CleanT>::resolved(std::forward<T>(arg));
+    when<Index>(data, promise);
+  }
+
+  template <typename... Args> void whenArgs(Args &&... args) {
+    typedef std::tuple<typename detail::RemovePromise<
+        typename std::remove_reference<Args>::type>::Type...>
+        Results;
+    /* We need to keep the results alive until the last promise
+     * finishes its execution
+     */
+
+    /* See the trick here ? Basically, we only have access to the real type of
+     * the results in this function. The policy classes do not have access to
+     * the full type (std::tuple), but, instead, take a generic template data
+     * type as a parameter. They only need to know that results is a tuple, they
+     * do not need to know the real type of the results.
+     *
+     * This is some sort of compile-time template type-erasing, hue
+     */
+    struct Data : public ContinuationPolicy::Data {
+      Data(size_t total, Resolver resolver, Rejection rejection)
+          : ContinuationPolicy::Data(total, std::move(resolver),
+                                     std::move(rejection)) {}
+
+      Results results;
+    };
+
+    auto data = std::make_shared<Data>(sizeof...(Args), std::move(resolve),
+                                       std::move(reject));
+    whenArgs<0>(data, std::forward<Args>(args)...);
+  }
+
+  template <size_t Index, typename Data, typename Head, typename... Rest>
+  void whenArgs(const Data &data, Head &&head, Rest &&... rest) {
+    when<Index>(data, std::forward<Head>(head));
+    whenArgs<Index + 1>(data, std::forward<Rest>(rest)...);
+  }
+
+  template <size_t Index, typename Data, typename Head>
+  void whenArgs(const Data &data, Head &&head) {
+    when<Index>(data, std::forward<Head>(head));
+  }
+
+  Resolver resolve;
+  Rejection reject;
+};
+
+template <typename T, typename Results> struct WhenAllRange {
+  WhenAllRange(Resolver _resolve, Rejection _reject)
+      : resolve(std::move(_resolve)), reject(std::move(_reject)) {}
+
+  template <typename Iterator> void operator()(Iterator first, Iterator last) {
+    auto data = std::make_shared<DataT<T>>(
+        static_cast<size_t>(std::distance(first, last)), std::move(resolve),
+        std::move(reject));
+
+    size_t index = 0;
+    for (auto it = first; it != last; ++it) {
+
+      WhenContinuation<T> cont(data, index);
+
+      it->then(std::move(cont), [=](std::exception_ptr ptr) {
+        std::lock_guard<std::mutex> guard(data->mtx);
+
+        if (data->rejected)
+          return;
+
+        data->rejected = true;
+        data->reject(std::move(ptr));
+      });
+
+      ++index;
+    }
+  }
+
+private:
+  struct Data {
+    Data(size_t _total, Resolver _resolver, Rejection _rejection)
+        : total(_total), resolved(0), rejected(false), mtx(),
+          resolve(std::move(_resolver)), reject(std::move(_rejection)) {}
+
+    const size_t total;
+    size_t resolved;
+    bool rejected;
+    std::mutex mtx;
+
+    Resolver resolve;
+    Rejection reject;
+  };
+
+  /* Ok so apparently I can not fully specialize a template structure
+   * here, so you know what, compiler ? Take that Dummy type and leave
+   * me alone
+   */
+  template <typename ValueType, typename Dummy = void>
+  struct DataT : public Data {
+    DataT(size_t total, Resolver resolver, Rejection rejection)
+        : Data(total, std::move(resolver), std::move(rejection)) {
+      results.resize(total);
+    }
+
+    Results results;
+  };
+
+  /* For a vector of void promises, we do not have any results, that's
+   * why we need a distinct specialization for the void case
+   */
+  template <typename Dummy> struct DataT<void, Dummy> : public Data {
+    DataT(size_t total, Resolver resolver, Rejection rejection)
+        : Data(total, std::move(resolver), std::move(rejection)) {}
+  };
+
+  template <typename ValueType, typename Dummy = void> struct WhenContinuation {
+    using D = std::shared_ptr<DataT<ValueType>>;
+
+    WhenContinuation(const D &_data, size_t _index)
+        : data(_data), index(_index) {}
+
+    void operator()(const ValueType &val) const {
+      std::lock_guard<std::mutex> guard(data->mtx);
+
+      if (data->rejected)
+        return;
+
+      data->results[index] = val;
+      data->resolved++;
+      if (data->resolved == data->total) {
+        data->resolve(data->results);
+      }
+    }
+
+    D data;
+    size_t index;
+  };
+
+  template <typename Dummy> struct WhenContinuation<void, Dummy> {
+    using D = std::shared_ptr<DataT<void>>;
+
+    WhenContinuation(const D &_data, size_t) : data(_data) {}
+
+    void operator()() const {
+      std::lock_guard<std::mutex> guard(data->mtx);
+
+      if (data->rejected)
+        return;
+
+      data->resolved++;
+      if (data->resolved == data->total) {
+        data->resolve();
+      }
     }
 
+    D data;
+  };
+
+  Resolver resolve;
+  Rejection reject;
+};
+
+} // namespace Impl
+
+template <typename... Args,
+          typename Results = std::tuple<typename detail::RemovePromise<
+              typename std::remove_reference<Args>::type>::Type...>>
+Promise<Results> whenAll(Args &&... args) {
+  // As ugly as it looks, this is needed to bypass a bug of gcc < 4.9
+  // whereby template parameters pack inside a lambda expression are not
+  // captured correctly and can not be expanded inside the lambda.
+  Resolver *resolve;
+  Rejection *reject;
+
+  Promise<Results> promise([&](Resolver &resolver, Rejection &rejection) {
+    resolve = &resolver;
+    reject = &rejection;
+  });
+
+  Impl::When<Impl::All> impl(std::move(*resolve), std::move(*reject));
+  // So we capture everything we need inside the lambda and then call the
+  // implementation and expand the parameters pack here
+  impl(std::forward<Args>(args)...);
+
+  return promise;
+}
+
+template <typename... Args> Promise<Any> whenAny(Args &&... args) {
+  // Same trick as above;
+  Resolver *resolve;
+  Rejection *reject;
+
+  Promise<Any> promise([&](Resolver &resolver, Rejection &rejection) {
+    resolve = &resolver;
+    reject = &rejection;
+  });
+
+  Impl::When<Impl::Any> impl(std::move(*resolve), std::move(*reject));
+  impl(std::forward<Args>(args)...);
+  return promise;
+}
+
+template <typename Iterator,
+          typename ValueType = typename detail::RemovePromise<
+              typename std::iterator_traits<Iterator>::value_type>::Type,
+          typename Results =
+              typename std::conditional<std::is_same<void, ValueType>::value,
+                                        void, std::vector<ValueType>>::type>
+Promise<Results> whenAll(Iterator first, Iterator last) {
+  /* @Security, assert that last >= first */
+
+  return Promise<Results>([=](Resolver &resolve, Rejection &rejection) {
+    Impl::WhenAllRange<ValueType, Results> impl(std::move(resolve),
+                                                std::move(rejection));
+
+    impl(first, last);
+  });
+}
+
 } // namespace Async
 } // namespace Pistache
diff --git a/include/pistache/router.h b/include/pistache/router.h
index 03468582a8146ac21968159da5522256b9f1c5c6..60008c0c8b0a83e5bb6402c6c34da6e68446add7 100644
--- a/include/pistache/router.h
+++ b/include/pistache/router.h
@@ -255,7 +255,8 @@ public:
    */
   explicit RouterHandler(std::shared_ptr<Rest::Router> router);
 
-  void onRequest(const Http::Request &req, Http::ResponseWriter response) override;
+  void onRequest(const Http::Request &req,
+                 Http::ResponseWriter response) override;
 
 private:
   std::shared_ptr<Tcp::Handler> clone() const final {