diff --git a/NextGen.cpp b/NextGen.cpp index 7e56564..8699319 100644 --- a/NextGen.cpp +++ b/NextGen.cpp @@ -111,10 +111,17 @@ auto appendHandlerToContinuation(Continuation&& cont, Handler&& handler) { #include #include #include +#include -/*struct ThisThreadDispatcher { - void operator() const() () -};*/ +struct SelfDispatcher { + template + void operator() (T&& callable) const { + std::forward(callable)(); + } +}; + +template +class ContinuableBase; static auto createEmptyContinuation() { return [](auto&& callback) { callback(); }; @@ -129,6 +136,32 @@ auto applyTuple(std::integer_sequence, T&& tuple, F&& function) { return std::forward(function)(std::get(std::forward(tuple))...); } +class Ownership { +public: + Ownership() { } + Ownership(Ownership const&) = default; + explicit Ownership(Ownership&& right) noexcept + : isOwningThis(takeOverFrom(std::move(right))) { }; + Ownership& operator = (Ownership const&) = default; + Ownership& operator = (Ownership&& right) noexcept { + isOwningThis = takeOverFrom(std::move(right)); + return *this; + } + + bool IsOwning() const noexcept { + return isOwningThis; + } + +private: + bool static takeOverFrom(Ownership&& right) { + bool value = right.isOwningThis; + right.isOwningThis = false; + return value; + } + + bool isOwningThis{ true }; +}; + /// Decorates none template struct CallbackResultDecorator { @@ -206,30 +239,98 @@ void invokeContinuation(Continuation&& continuation) { std::forward(continuation)(createEmptyCallback()); } -static auto makeTestContinuation() { - return [](auto&& callback) { - callback("
hi
"); +template +auto make_continuable(Continuation&& continuation, + Dispatcher&& dispatcher = SelfDispatcher{}) noexcept { + return ContinuableBase, std::decay_t> { + std::forward(continuation), std::forward(dispatcher) }; } +template +class ContinuableBase { + template + friend class ContinuableBase; + + ContinuableBase(Continuation continuation_, Ownership ownership_, + Dispatcher dispatcher_) noexcept + : continuation(std::move(continuation_)), + dispatcher(std::move(dispatcher_)), ownership(std::move(ownership_)) { } + +public: + ContinuableBase(Continuation continuation_, + Dispatcher dispatcher_ = Dispatcher{}) noexcept + : continuation(std::move(continuation_)), + dispatcher(std::move(dispatcher_)) { } + ~ContinuableBase() { + if (ownership.IsOwning()) { + invokeContinuation(std::move(continuation)); + } + } + ContinuableBase(ContinuableBase&&) = default; + ContinuableBase(ContinuableBase const&) = default; + + template + auto then(Callback&& callback)&& { + auto next = appendHandlerToContinuation(std::move(continuation), + std::forward(callback)); + return ContinuableBase, Dispatcher> { + std::move(next), std::move(ownership), std::move(dispatcher) + }; + } + + template + auto then(Callback&& callback) const& { + auto next = appendHandlerToContinuation(continuation, + std::forward(callback)); + return ContinuableBase, Dispatcher> { + std::move(next), ownership, dispatcher + }; + } + + template + auto post(NewStrand&& newStrand)&& { + return ContinuableBase { + std::move(continuation), std::move(ownership), + std::forward(newStrand) + }; + } + + template + auto post(NewStrand&& newStrand) const& { + return ContinuableBase { + continuation, ownership, + std::forward(newStrand) + }; + } + +private: + Continuation continuation; + Dispatcher dispatcher; + Ownership ownership; +}; + +static auto makeTestContinuation() { + return make_continuable([i = std::make_unique(0)](auto&& callback) { + callback("
hi
"); + }); +} + int main(int, char**) { + auto dispatcher = [](auto callable) { + + }; + int res = 0; - auto continuation = makeTestContinuation(); + makeTestContinuation() + .post(dispatcher) + .then([](std::string) { + return std::make_tuple(47, 46, 45); + }) + .then([&](int val1, int val2, int val3) { + res += val1 + val2 + val3; + int i = 0; + }); - auto then1 = [](std::string) { - int i = 0; - - return std::make_tuple(47, 46, 45); - }; - - auto then2 = [&](int val1, int val2, int val3) { - res = val1 + val2 + val3; - int i = 0; - }; - - auto f1 = appendHandlerToContinuation(continuation, then1); - auto f2 = appendHandlerToContinuation(f1, then2); - - invokeContinuation(f2); return res; }