diff --git a/include/continuable/detail/composition.hpp b/include/continuable/detail/composition.hpp index e9f4da1..d78ae22 100644 --- a/include/continuable/detail/composition.hpp +++ b/include/continuable/detail/composition.hpp @@ -38,8 +38,10 @@ #include #include +#include #include #include +#include #include #include @@ -130,6 +132,26 @@ class all_result_submitter : public std::enable_shared_from_this< std::once_flag flag_; std::tuple result_; + template + struct partial_callback { + 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) { + (*this)(std::forward(args)...); + } + + void set_exception(types::error_type error) { + (*this)(types::dispatch_error_tag{}, std::move(error)); + } + }; + public: explicit all_result_submitter(T callback) : callback_(std::move(callback)), left_(Submissions) { @@ -139,13 +161,7 @@ public: template auto create_callback(traits::size_constant /*from*/, traits::size_constant /*to*/) { - - return [me = this->shared_from_this()](auto&&... args) { - // Resolve the and composition with the given arguments at the - // stored position - me->resolve(traits::size_constant{}, traits::size_constant{}, - std::forward(args)...); - }; + return partial_callback{this->shared_from_this()}; } private: @@ -195,9 +211,12 @@ private: }; /// Invokes the callback with the first arriving result -template -class any_result_submitter - : public std::enable_shared_from_this>, +template +class any_result_submitter; +template +class any_result_submitter, T> + : public std::enable_shared_from_this< + any_result_submitter, T>>, public util::non_movable { T callback_; @@ -209,16 +228,21 @@ public: /// Creates a submitter which submits it's result to the callback auto create_callback() { - return [me = this->shared_from_this()](auto&&... args) { + auto callback = [me = this->shared_from_this()](auto&&... args) { me->invoke(std::forward(args)...); }; + + return promise_base, + hints::signature_hint_tag>( + std::move(callback)); } private: // Invokes the callback with the given arguments - template - void invoke(Args&&... args) { - std::call_once(flag_, std::move(callback_), std::forward(args)...); + template + void invoke(ActualArgs&&... args) { + std::call_once(flag_, std::move(callback_), + std::forward(args)...); } }; } // namespace detail @@ -355,10 +379,10 @@ auto finalize_composition( } /// Creates a submitter that continues `any` chains -template -auto make_any_result_submitter(Callback&& callback) { - return std::make_shared< - detail::any_result_submitter>>( +template +auto make_any_result_submitter(Signature&& /*signature*/, Callback&& callback) { + return std::make_shared, std::decay_t>>( std::forward(callback)); } @@ -409,13 +433,15 @@ auto finalize_composition( base::hint_of(traits::identity_of(args))...); }); + using Signature = decltype(signature); + 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 = make_any_result_submitter( - std::forward(callback)); + Signature{}, std::forward(callback)); traits::static_for_each_in(std::move(composition), [&](auto&& entry) mutable { diff --git a/test/unit-test/test-continuable.hpp b/test/unit-test/test-continuable.hpp index 16252c6..6c635fe 100644 --- a/test/unit-test/test-continuable.hpp +++ b/test/unit-test/test-continuable.hpp @@ -89,11 +89,9 @@ auto to_hint(identity hint) { template auto supplier_of(Args&&... args) { return [values = std::make_tuple(std::forward(args)...)]( - auto&& callback) mutable { + auto&& promise) mutable { cti::detail::traits::unpack(std::move(values), [&](auto&&... passed) { - // ... - std::forward(callback)( - std::forward(passed)...); + promise.set_value(std::forward(passed)...); }); }; } @@ -104,8 +102,8 @@ public: template auto invoke(T&& type) { return this->make(identity<>{}, identity{}, - [type = std::forward(type)](auto&& callback) mutable { - std::forward(callback)(); + [type = std::forward(type)](auto&& promise) mutable { + promise.set_value(); }); } @@ -120,10 +118,7 @@ public: }; inline auto empty_caller() { - return [](auto&& callback) { - // ... - std::forward(callback)(); - }; + return [](auto&& promise) { promise.set_value(); }; } inline auto empty_continuable() {