/* * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License Version 2.0 with LLVM Exceptions * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * https://llvm.org/LICENSE.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include namespace unifex { namespace _bulk_join { template struct _join_receiver { class type; }; template using join_receiver = typename _join_receiver::type; template class _join_receiver::type { public: template(typename Receiver2) (requires constructible_from) explicit type(Receiver2&& r) noexcept(std::is_nothrow_constructible_v) : receiver_((Receiver2&&)r) {} void set_next() & noexcept {} template(typename... Values) (requires receiver_of) void set_value(Values&&... values) noexcept(is_nothrow_receiver_of_v) { unifex::set_value(std::move(receiver_), (Values&&)values...); } template(typename Error) (requires receiver) void set_error(Error&& error) noexcept { unifex::set_error(std::move(receiver_), (Error&&)error); } void set_done() noexcept { unifex::set_done(std::move(receiver_)); } friend constexpr unifex::parallel_unsequenced_policy tag_invoke( tag_t, [[maybe_unused]] const type& r) noexcept { return {}; } template(typename CPO, typename Self) (requires is_receiver_query_cpo_v AND same_as) friend auto tag_invoke(CPO cpo, const Self& self) noexcept(is_nothrow_callable_v) -> callable_result_t { return cpo(self.receiver_); } private: Receiver receiver_; }; template struct _join_sender { class type; }; template using join_sender = typename _join_sender::type; template class _join_sender::type { public: template class Variant, template class Tuple> using value_types = sender_value_types_t; template class Variant> using error_types = sender_error_types_t; static constexpr bool sends_done = sender_traits::sends_done; template explicit type(Source2&& s) noexcept(std::is_nothrow_constructible_v) : source_((Source2&&)s) {} template(typename Self, typename Receiver) (requires same_as, type> AND sender_to, join_receiver>>) friend auto tag_invoke(tag_t, Self&& self, Receiver&& r) noexcept( std::is_nothrow_constructible_v> && is_nothrow_connectable_v, join_receiver>>) -> connect_result_t, join_receiver>> { return unifex::connect( static_cast(self).source_, join_receiver>{static_cast(r)}); } private: Source source_; }; struct _fn { template(typename Source) (requires typed_bulk_sender && tag_invocable<_fn, Source>) auto operator()(Source&& source) const noexcept(is_nothrow_tag_invocable_v<_fn, Source>) -> tag_invoke_result_t<_fn, Source> { return tag_invoke(_fn{}, (Source&&)source); } template(typename Source) (requires typed_bulk_sender && (!tag_invocable<_fn, Source>)) auto operator()(Source&& source) const noexcept(std::is_nothrow_constructible_v, Source>) -> join_sender> { return join_sender>{ (Source&&)source}; } constexpr auto operator()() const noexcept(is_nothrow_callable_v< tag_t, _fn>) -> bind_back_result_t<_fn> { return bind_back(*this); } }; } // namespace _bulk_join inline constexpr _bulk_join::_fn bulk_join{}; } // namespace unifex #include