diff --git a/include/continuable/detail/composition-all.hpp b/include/continuable/detail/composition-all.hpp index 12bf654..8eecfee 100644 --- a/include/continuable/detail/composition-all.hpp +++ b/include/continuable/detail/composition-all.hpp @@ -49,30 +49,55 @@ namespace cti { namespace detail { namespace composition { namespace all { -template -constexpr void assign(traits::size_constant /*pos*/, T& /*storage*/) { - // ... -} -template -void assign(traits::size_constant pos, T& storage, Current&& current, - Args&&... args) { - // TODO Improve this -> linear instantiation - std::get(storage) = std::forward(current); - assign(pos + traits::size_constant_of<1>(), storage, - std::forward(args)...); -} +struct all_hint_deducer { + static constexpr auto deduce(hints::signature_hint_tag<>) noexcept + -> decltype(spread_this()); + + template + static constexpr auto deduce(hints::signature_hint_tag) -> First; + + template + static constexpr auto + deduce(hints::signature_hint_tag) + -> decltype(spread_this(std::declval(), std::declval(), + std::declval()...)); + + template < + typename T, + std::enable_if_t>::value>* = nullptr> + auto operator()(T&& /*continuable*/) const + -> decltype(deduce(hints::hint_of(traits::identify{}))); +}; + +constexpr auto deduce_from_pack(traits::identity) + -> hints::signature_hint_tag<>; +template +constexpr auto deduce_from_pack(traits::identity>) + -> hints::signature_hint_tag; +template +constexpr auto deduce_from_pack(traits::identity) + -> hints::signature_hint_tag; + +// We must guard the mapped type against to be void since this represents an +// empty signature hint. +template +constexpr auto deduce_hint(Composition && /*composition*/) + -> decltype(deduce_from_pack( + traits::identity()))>{})){}; /// Caches the partial results and invokes the callback when all results /// are arrived. This class is thread safe. -template +template class all_result_submitter : public std::enable_shared_from_this< - all_result_submitter>, + all_result_submitter>, public util::non_movable { - T callback_; + Callback callback_; + Result result_; + std::atomic left_; std::once_flag flag_; - std::tuple result_; template void resolve(traits::size_constant from, traits::size_constant, @@ -118,95 +143,47 @@ class all_result_submitter : public std::enable_shared_from_this< } } - template + template struct partial_all_callback { + Target* target_; std::shared_ptr me_; template void operator()(PartialArgs&&... args) && { - me_->resolve(traits::size_constant{}, traits::size_constant{}, - std::forward(args)...); } template - void set_value(PartialArgs&&... args) { - std::move (*this)(std::forward(args)...); - } - - void set_exception(types::error_type error) { - std::move (*this)(types::dispatch_error_tag{}, std::move(error)); + void operator()(types::dispatch_error_tag, types::error_type) && { } }; public: - explicit all_result_submitter(T callback) - : callback_(std::move(callback)), left_(Submissions) { + explicit all_result_submitter(Callback callback, Result&& result) + : callback_(std::move(callback)), result_(std::move(result)), left_(1) { } - /// Creates a submitter which submits it's result into the tuple - template - auto create_callback(traits::size_constant /*from*/, - traits::size_constant /*to*/) { - return partial_all_callback{this->shared_from_this()}; + /// Creates a submitter which submits it's result into the storage + template + auto create_callback(Target* target) { + left_.fetch_add(1, std::memory_order_seq_cst); + return partial_all_callback>{target, + this->shared_from_this()}; + } + + /// Initially the counter is created with an initial count of 1 in order + /// to prevent that the composition is finished before all callbacks + /// were registered. + void start_accept() { } }; -/// Creates a submitter which caches the intermediate results of `all` chains -template -auto make_all_result_submitter(Callback&& callback, - traits::size_constant, - traits::identity) { - return std::make_shared, - Submissions, Args...>>( - std::forward(callback)); -} - -/// A callable object to merge multiple signature hints together -struct entry_merger { - template - constexpr auto operator()(T&&...) const noexcept { - return traits::merge(hints::hint_of(traits::identify())...); +struct continuable_dispatcher { + template >::value>* = nullptr> + auto operator()(Index* index, Target* target) const noexcept { } }; - -struct all_hint_deducer { - static constexpr auto deduce(hints::signature_hint_tag<>) noexcept { - return spread_this(); - } - template - static constexpr auto deduce(hints::signature_hint_tag) { - return First{}; - } - template - static constexpr auto - deduce(hints::signature_hint_tag) { - return spread_this(First{}, Second{}, Args{}...); - } - - template < - typename T, - std::enable_if_t>::value>* = nullptr> - auto operator()(T&& /*continuable*/) const { - return deduce(hints::hint_of(traits::identify{})); - } -}; - -constexpr auto deduce_from_pack(traits::identity) - -> hints::signature_hint_tag<>; -template -constexpr auto deduce_from_pack(traits::identity>) - -> hints::signature_hint_tag; -template -constexpr auto deduce_from_pack(traits::identity) - -> hints::signature_hint_tag; - -// We must guard the mapped type against to be void since this represents an -// empty signature hint. -template -constexpr auto deduce_hint(Composition && /*composition*/) - -> decltype(deduce_from_pack( - traits::identity()))>{})){}; } // namespace all /// Finalizes the all logic of a given composition @@ -223,52 +200,10 @@ struct composition_finalizer { return [composition = std::forward(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; }; - - constexpr auto const signature = hint(); - - // 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); - - // 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)); - - // 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))); - - // 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); - }); + auto result = + remapping::create_result_pack(std::forward(composition)); }; } - - /*template - static auto finalize_new(Composition&& composition) { - return [composition = std::forward(composition)]( - auto&& callback) mutable { - // TODO - }; - }*/ }; } // namespace composition } // namespace detail diff --git a/include/continuable/detail/composition-remapping.hpp b/include/continuable/detail/composition-remapping.hpp index 76c3fb8..5405b98 100644 --- a/include/continuable/detail/composition-remapping.hpp +++ b/include/continuable/detail/composition-remapping.hpp @@ -81,6 +81,20 @@ struct unpack_result_guards { } }; +constexpr void_result_guard wrap() { + return {}; +} +template +constexpr decltype(auto) wrap(First&& first) { + return std::forward(first); +} +template +constexpr decltype(auto) wrap(First&& first, Second&& second, Rest&&... rest) { + return std::make_tuple(std::forward(first), + std::forward(second), + std::forward(rest)...); +} + namespace detail { struct result_extractor_mapper { /// Create slots for a void result which is removed later. diff --git a/include/continuable/detail/composition-seq.hpp b/include/continuable/detail/composition-seq.hpp index c907a9c..c50ad4d 100644 --- a/include/continuable/detail/composition-seq.hpp +++ b/include/continuable/detail/composition-seq.hpp @@ -42,6 +42,7 @@ #include #include #include +#include namespace cti { namespace detail { @@ -122,20 +123,6 @@ struct index_relocator { } }; -constexpr remapping::void_result_guard wrap() { - return {}; -} -template -constexpr decltype(auto) wrap(First&& first) { - return std::forward(first); -} -template -constexpr decltype(auto) wrap(First&& first, Second&& second, Rest&&... rest) { - return std::make_tuple(std::forward(first), - std::forward(second), - std::forward(rest)...); -} - template struct sequential_dispatch_data { Callback callback; @@ -145,7 +132,8 @@ struct sequential_dispatch_data { template class sequential_dispatch_visitor - : public std::enable_shared_from_this> { + : public std::enable_shared_from_this>, + public util::non_movable { Data data_; @@ -181,7 +169,7 @@ public: next = std::forward(next) ](auto&&... args) mutable { // Assign the result to the target - *target = wrap(std::forward(args)...); + *target = remapping::wrap(std::forward(args)...); // Continue the asynchronous sequential traversal next(); diff --git a/include/continuable/detail/composition.hpp b/include/continuable/detail/composition.hpp index 1c25f7b..1278d7a 100644 --- a/include/continuable/detail/composition.hpp +++ b/include/continuable/detail/composition.hpp @@ -142,7 +142,7 @@ auto connect(Strategy strategy, continuable_base&& left, template struct composition_finalizer; -/// Finalizes the any logic of a given composition +/// Finalizes the connection logic of a given composition template auto finalize_composition(continuable_base&& continuation) { using finalizer = composition_finalizer; @@ -197,6 +197,7 @@ struct prepare_continuables { continuable.freeze(); // Materialize every continuable + // TODO Actually we would just need to consume the data here return base::attorney::materialize(std::forward(continuable)); } };