diff --git a/include/continuable/continuable-base.hpp b/include/continuable/continuable-base.hpp index 8057450..62d9f6c 100644 --- a/include/continuable/continuable-base.hpp +++ b/include/continuable/continuable-base.hpp @@ -608,8 +608,7 @@ private: OAnnotation>::value>* = nullptr> static auto materializeImpl(continuable_base&& continuable) { - using finalizer = detail::composition::composition_finalizer; - return finalizer::finalize(std::move(continuable)); + return detail::composition::finalize_composition(std::move(continuable)); } Data&& consume_data() && { diff --git a/include/continuable/detail/composition.hpp b/include/continuable/detail/composition.hpp index 499111b..d13d92b 100644 --- a/include/continuable/detail/composition.hpp +++ b/include/continuable/detail/composition.hpp @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -126,11 +127,46 @@ auto connect(Strategy strategy, continuable_base&& left, return base::attorney::create(std::move(data), strategy, ownership_); } -/// All strategies should specialize this class in order to provide -/// a finalize static method. +/// All strategies should specialize this class in order to provide: +/// - A finalize static method that creates the callable object which +/// is invoked with the callback to call when the composition is finished. +/// - A static method hint that returns the new signature hint. template struct composition_finalizer; +struct aggregate_ownership { + util::ownership& ownership_; + + template >::value>* = nullptr> + auto operator()(Continuable const& continuable) noexcept { + util::ownership other = base::attorney::ownership_of(continuable); + /*if (!other.is_default())*/ { ownership_ |= other; } + } +}; + +// Merges the ownership of all continuables involved into the strategy +/*if (ownership.is_acquired() || !ownership.is_frozen()) { + traverse_pack(aggregate_ownership{ownership}, composition); +}*/ + +/// Finalizes the any logic of a given composition +template +auto finalize_composition(continuable_base&& continuation) { + using finalizer = composition_finalizer; + + util::ownership ownership = base::attorney::ownership_of(continuation); + auto composition = base::attorney::consume_data(std::move(continuation)); + + // Retrieve the new signature hint + constexpr auto const signature = + finalizer::template hint(); + + // Return a new continuable which + return base::attorney::create(finalizer::finalize(std::move(composition)), + signature, std::move(ownership)); +} } // namespace composition } // namespace detail } // namespace cti diff --git a/include/continuable/detail/composition_all.hpp b/include/continuable/detail/composition_all.hpp index 34bcb50..fce2291 100644 --- a/include/continuable/detail/composition_all.hpp +++ b/include/continuable/detail/composition_all.hpp @@ -172,59 +172,55 @@ struct entry_merger { /// Finalizes the all logic of a given composition template <> struct composition_finalizer { + template + static constexpr auto hint() { + return decltype( + traits::unpack(std::declval(), all::entry_merger{})){}; + } + /// Finalizes the all logic of a given composition - template - static auto finalize(Continuable&& continuation) { + template + static auto finalize(Composition&& composition) { + return [composition = std::forward(composition)]( + auto&& callback) mutable { - auto ownership_ = base::attorney::ownership_of(continuation); + // We mark the current 2-dimensional position through a pair: + // std::pair, size_constant> + // ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~ + // Continuation pos Result pos + constexpr auto const begin = std::make_pair( + traits::size_constant_of<0>(), traits::size_constant_of<0>()); + constexpr auto const pack = traits::identify{}; + constexpr auto const end = traits::pack_size_of(pack); + auto const condition = [=](auto pos) { return pos.first < end; }; - auto composition = - base::attorney::consume_data(std::forward(continuation)); + constexpr auto const signature = hint(); - // Merge all signature hints together - constexpr auto const signature = - traits::unpack(composition, all::entry_merger{}); + // Create the result submitter which caches all results and invokes + // the final callback upon completion. + auto submitter = all::make_all_result_submitter( + std::forward(callback), end, signature); - return base::attorney::create( - [ signature, - composition = std::move(composition) ](auto&& callback) mutable { - // We mark the current 2-dimensional position through a pair: - // std::pair, size_constant> - // ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~ - // Continuation pos Result pos - constexpr auto const begin = std::make_pair( - traits::size_constant_of<0>(), traits::size_constant_of<0>()); - constexpr auto const pack = traits::identify{}; - constexpr auto const end = traits::pack_size_of(pack); - auto const condition = [=](auto pos) { return pos.first < end; }; + // Invoke every continuation with it's callback of the submitter + traits::static_while(begin, condition, [&](auto current) mutable { + auto entry = + std::move(std::get(composition)); - // Create the result submitter which caches all results and invokes - // the final callback upon completion. - auto submitter = all::make_all_result_submitter( - std::forward(callback), end, signature); + // This is the length of the arguments of the current continuable + constexpr auto const arg_size = + traits::pack_size_of(hints::hint_of(traits::identity_of(entry))); - // Invoke every continuation with it's callback of the submitter - traits::static_while(begin, condition, [&](auto current) mutable { - auto entry = std::move( - std::get(composition)); + // The next position in the result tuple + constexpr auto const next = current.second + arg_size; - // This is the length of the arguments of the current continuable - constexpr auto const arg_size = traits::pack_size_of( - hints::hint_of(traits::identity_of(entry))); + // Invoke the continuation with the associated submission callback + base::attorney::invoke_continuation( + std::move(entry), submitter->create_callback(current.second, next)); - // The next position in the result tuple - constexpr auto const next = current.second + arg_size; - - // Invoke the continuation with the associated submission callback - base::attorney::invoke_continuation( - std::move(entry), - submitter->create_callback(current.second, next)); - - return std::make_pair(current.first + traits::size_constant_of<1>(), - next); - }); - }, - signature, std::move(ownership_)); + return std::make_pair(current.first + traits::size_constant_of<1>(), + next); + }); + }; } }; } // namespace composition diff --git a/include/continuable/detail/composition_any.hpp b/include/continuable/detail/composition_any.hpp index c01144f..cb9f6d8 100644 --- a/include/continuable/detail/composition_any.hpp +++ b/include/continuable/detail/composition_any.hpp @@ -153,35 +153,30 @@ private: /// Finalizes the any logic of a given composition template <> struct composition_finalizer { - template - static auto finalize(Continuable&& continuation) { + template + static constexpr auto hint() { + return decltype(traits::unpack(std::declval(), + any::determine_shared_result{})){}; + } - auto ownership = base::attorney::ownership_of(continuation); + template + static auto finalize(Composition&& composition) { + return [composition = std::forward(composition)]( + auto&& callback) mutable { + // Create the submitter which calls the given callback once at the + // first callback invocation. + auto submitter = any::make_any_result_submitter( + std::forward(callback)); - auto composition = - base::attorney::consume_data(std::forward(continuation)); - - constexpr auto const signature = - traits::unpack(composition, any::determine_shared_result{}); - - return base::attorney::create( - [composition = std::move(composition)](auto&& callback) mutable { - - // Create the submitter which calls the given callback once at the - // first callback invocation. - auto submitter = any::make_any_result_submitter( - std::forward(callback)); - - traits::static_for_each_in(std::move(composition), - [&](auto&& entry) mutable { - // Invoke the continuation with a - // submission callback - base::attorney::invoke_continuation( - std::forward(entry), - submitter->create_callback()); - }); - }, - signature, std::move(ownership)); + traits::static_for_each_in(std::move(composition), + [&](auto&& entry) mutable { + // Invoke the continuation with a + // submission callback + base::attorney::invoke_continuation( + std::forward(entry), + submitter->create_callback()); + }); + }; } }; } // namespace composition diff --git a/include/continuable/detail/util.hpp b/include/continuable/detail/util.hpp index c025b59..1b20f33 100644 --- a/include/continuable/detail/util.hpp +++ b/include/continuable/detail/util.hpp @@ -202,6 +202,16 @@ public: return *this; } + // Assigns the right ownership to this one + ownership& operator|=(ownership const& right) noexcept { + if (!right.is_acquired()) { + release(); + } + if (right.is_frozen()) { + freeze(); + } + return *this; + } // Merges both ownerships together ownership operator|(ownership const& right) const noexcept { return ownership(is_acquired() && right.is_acquired(), @@ -214,6 +224,10 @@ public: constexpr bool is_frozen() const noexcept { return frozen_; } + /// Returns true when the ownership is in the default state + constexpr bool is_default() const noexcept { + return is_acquired() && !is_frozen(); + } void release() noexcept { assert(is_acquired() && "Tried to release the ownership twice!");