From 90a12e10f71e45b7a7ded8ea1d2bfc970d7b2a9c Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Thu, 15 Sep 2016 01:03:51 +0200 Subject: [PATCH] Add lazy undecoration --- NextGen.cpp | 201 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 129 insertions(+), 72 deletions(-) diff --git a/NextGen.cpp b/NextGen.cpp index 8401e15..b6f6e4b 100644 --- a/NextGen.cpp +++ b/NextGen.cpp @@ -108,8 +108,10 @@ auto appendHandlerToContinuation(Continuation&& cont, Handler&& handler) { }; } */ +#include #include #include +#include #include #include @@ -141,30 +143,42 @@ public: Ownership() { } Ownership(Ownership const&) = default; explicit Ownership(Ownership&& right) noexcept - : isOwningThis(takeOverFrom(std::move(right))) { }; + : isOwningThis(std::exchange(right.isOwningThis, false)) { }; Ownership& operator = (Ownership const&) = default; Ownership& operator = (Ownership&& right) noexcept { - isOwningThis = takeOverFrom(std::move(right)); + isOwningThis = std::exchange(right.isOwningThis, false); return *this; } - bool IsOwning() const noexcept { + bool hasOwnership() const noexcept { return isOwningThis; } -private: - bool static takeOverFrom(Ownership&& right) { - bool value = right.isOwningThis; - right.isOwningThis = false; - return value; + void invalidate() { + isOwningThis = false; } +private: bool isOwningThis{ true }; }; -/// Decorates none -template +/// Decorates single values +template struct CallbackResultDecorator { + template + static auto decorate(Callback&& callback) { + return [callback = std::forward(callback)](auto&&... args) { + Value value = callback(std::forward(args)...); + return [value = std::move(value)](auto&& callback) mutable { + callback(std::move(value)); + }; + }; + } +}; + +/// No decoration is needed for continuables +template +struct CallbackResultDecorator>{ template static auto decorate(Callback&& callback) { return std::forward(callback); @@ -223,8 +237,7 @@ auto createProxyCallback(Callback&& callback, template auto appendCallback(Continuation&& continuation, - Callback&& callback) { - + Callback&& callback) { return [continuation = std::forward(continuation), callback = std::forward(callback)](auto&& next) mutable { // Invoke the next invocation handler @@ -233,10 +246,13 @@ auto appendCallback(Continuation&& continuation, }; } -template -void invokeContinuation(Continuation&& continuation) { - // Pass an empty callback to the continuation to invoke it - std::forward(continuation)(createEmptyCallback()); +template +void invokeContinuation(Data data) { + // Check whether the ownership is acquired and start the continuation call + if (data.ownership.hasOwnership()) { + // Pass an empty callback to the continuation to invoke it + std::move(data.continuation)(createEmptyCallback()); + } } template @@ -255,91 +271,134 @@ struct ContinuableConfig { >; }; +/// +template +struct ContinuableData { + using Config = ConfigType; + + ContinuableData(Ownership ownership_, + typename Config::Continuation continuation_, + typename Config::Dispatcher dispatcher_) noexcept + : ownership(std::move(ownership_)), + continuation(std::move(continuation_)), + dispatcher(std::move(dispatcher_)) { } + + Ownership ownership; + typename Config::Continuation continuation; + typename Config::Dispatcher dispatcher; +}; + +/// The DefaultDecoration is a container for already materialized +/// ContinuableData which can be accessed instantly. +template +class DefaultDecoration { +public: + DefaultDecoration(Data data_) + : data(std::move(data_)) { } + + using Config = typename Data::Config; + + /// Return a r-value reference to the data + Data&& undecorate()&& { + return std::move(data); + } + /// Return a copy of the data + Data undecorate() const& { + return data; + } + +private: + Data data; +}; + template auto make_continuable(Continuation&& continuation, Dispatcher&& dispatcher = SelfDispatcher{}) noexcept { - using Config = ContinuableConfig< + using Decoration = DefaultDecoration, std::decay_t - >; - return ContinuableBase { + >>>; + return ContinuableBase { { { + { }, std::forward(continuation), std::forward(dispatcher) - }; + } } }; } -template +template +auto thenImpl(Data data, Callback&& callback) { + auto next = appendCallback(std::move(data.continuation), + std::forward(callback)); + using Decoration = DefaultDecoration + >>; + return ContinuableBase { { + { std::move(data.ownership), std::move(next), std::move(data.dispatcher) } + } }; +} + +template +auto postImpl(Data&& data ,NewDispatcher&& newDispatcher) { + /*->ContinuableBase>> { + return{ std::move(continuation), std::move(ownership), + std::forward(newDispatcher) }; */ + + return 0; +} + + +template class ContinuableBase { template friend class ContinuableBase; - ContinuableBase(typename Config::Continuation continuation_, - Ownership ownership_, - typename Config::Dispatcher dispatcher_) noexcept - : continuation(std::move(continuation_)), - dispatcher(std::move(dispatcher_)), ownership(std::move(ownership_)) { } - public: - ContinuableBase(typename Config::Continuation continuation_, - typename Config::Dispatcher dispatcher_) noexcept - : continuation(std::move(continuation_)), - dispatcher(std::move(dispatcher_)) { } + explicit ContinuableBase(Decoration decoration_) + : decoration(std::move(decoration_)) { } + ~ContinuableBase() { - if (ownership.IsOwning()) { - invokeContinuation(std::move(continuation)); - } + // Undecorate/materialize the decoration + invokeContinuation(std::move(decoration).undecorate()); } ContinuableBase(ContinuableBase&&) = default; ContinuableBase(ContinuableBase const&) = default; template auto then(Callback&& callback)&& { - auto next = appendCallback(std::move(continuation), - std::forward(callback)); - using Transformed = ContinuableBase< - typename Config::template ChangeContinuationTo - >; - return Transformed { - std::move(next), std::move(ownership), std::move(dispatcher) - }; + return thenImpl(std::move(decoration).undecorate(), + std::forward(callback)); } template auto then(Callback&& callback) const& { - auto next = appendCallback(continuation, std::forward(callback)); - using Transformed = ContinuableBase< - typename Config::template ChangeContinuationTo - >; - return Transformed { - std::move(next), ownership, dispatcher - }; + return thenImpl(decoration.undecorate(), + std::forward(callback)); } template - auto post(NewDispatcher&& newDispatcher)&& - -> ContinuableBase>> { - return { std::move(continuation), std::move(ownership), - std::forward(newDispatcher) }; + auto post(NewDispatcher&& newDispatcher)&& { + return postImpl(std::move(decoration).undecorate(), + std::forward(newDispatcher)); } template - auto post(NewDispatcher&& newDispatcher) const& - -> ContinuableBase>> { - return { continuation, ownership, - std::forward(newDispatcher) }; + auto post(NewDispatcher&& newDispatcher) const& { + return postImpl(decoration.undecorate(), + std::forward(newDispatcher)); } private: - typename Config::Continuation continuation; - typename Config::Dispatcher dispatcher; - Ownership ownership; + /// The Decoration represents the possible lazy materialized + /// data of the continuable. + /// The decoration pattern is used to make it possible to allow lazy chaining + /// of operators on Continuables like the and expression `&&`. + Decoration decoration; }; static auto makeTestContinuation() { return make_continuable([](auto&& callback) { - callback("
hi
"); + callback("47"); }); } @@ -348,17 +407,15 @@ int main(int, char**) { int res = 0; makeTestContinuation() - .post(dispatcher) - .then([](std::string) { - - + // .post(dispatcher) + .then([](std::string /*str*/) { return std::make_tuple(47, 46, 45); }) - .then([&](int val1, int val2, int val3) { - - - res += val1 + val2 + val3; - int i = 0; + .then([](int val1, int val2, int val3) { + return val1 + val2 + val3; + }) + .then([&](int val) { + res += val; }); return res;