/* * 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 namespace unifex { namespace _schedule { struct _fn; template UNIFEX_CONCEPT_FRAGMENT( // _with_tag_invoke_helper, // requires () (0) && tag_invocable<_fn, Scheduler> && sender>); template UNIFEX_CONCEPT // _with_tag_invoke = // UNIFEX_FRAGMENT(_schedule::_with_tag_invoke_helper, Scheduler); template using _member_schedule_result_t = decltype(UNIFEX_DECLVAL(Scheduler).schedule()); template UNIFEX_CONCEPT_FRAGMENT( // _has_member_schedule_, // requires() (0) && sender<_member_schedule_result_t>); template UNIFEX_CONCEPT // _with_member_schedule = // UNIFEX_FRAGMENT(_schedule::_has_member_schedule_, Scheduler); struct sender; inline const struct _fn { private: template static auto _select() noexcept { if constexpr (_with_tag_invoke) { return meta_tag_invoke_result<_fn>{}; } else if constexpr (_with_member_schedule) { return meta_quote1<_member_schedule_result_t>{}; } else { return type_always{}; } } template using _result_t = typename decltype(_fn::_select())::template apply; public: template(typename Scheduler) (requires _with_tag_invoke) constexpr auto operator()(Scheduler&& s) const noexcept(is_nothrow_tag_invocable_v<_fn, Scheduler>) -> _result_t { return tag_invoke(_fn{}, static_cast(s)); } template(typename Scheduler) (requires (!_with_tag_invoke) AND _with_member_schedule) constexpr auto operator()(Scheduler&& s) const noexcept( noexcept(static_cast(s).schedule())) -> _result_t { return static_cast(s).schedule(); } constexpr sender operator()() const noexcept; } schedule{}; } // namespace _schedule using _schedule::schedule; template using schedule_result_t = decltype(schedule(UNIFEX_DECLVAL(S&&))); // Define the scheduler concept without the macros for better diagnostics #if UNIFEX_CXX_CONCEPTS template concept // scheduler = // requires(S&& s) { schedule((S&&) s); } && equality_comparable> && copy_constructible>; #else template UNIFEX_CONCEPT_FRAGMENT( // _scheduler, requires(S&& s) ( schedule((S&&) s) )); template UNIFEX_CONCEPT // scheduler = // UNIFEX_FRAGMENT(unifex::_scheduler, S) && equality_comparable> && copy_constructible>; #endif namespace _get_scheduler { inline const struct _fn { template (typename SchedulerProvider) (requires tag_invocable<_fn, const SchedulerProvider&>) auto operator()(const SchedulerProvider& context) const noexcept -> tag_invoke_result_t<_fn, const SchedulerProvider&> { static_assert(is_nothrow_tag_invocable_v<_fn, const SchedulerProvider&>); static_assert( scheduler>); return tag_invoke(*this, context); } } get_scheduler{}; } // namespace _get_scheduler using _get_scheduler::get_scheduler; template using get_scheduler_result_t = decltype(get_scheduler(UNIFEX_DECLVAL(SchedulerProvider&&))); // Define the scheduler concept without the macros for better diagnostics #if UNIFEX_CXX_CONCEPTS template concept // scheduler_provider = // requires(SP&& sp) { get_scheduler((SP&&) sp); }; #else template UNIFEX_CONCEPT_FRAGMENT( // _scheduler_provider, requires(SP&& sp) ( get_scheduler((SP&&) sp) )); template UNIFEX_CONCEPT // scheduler_provider = // UNIFEX_FRAGMENT(unifex::_scheduler_provider, SP); #endif namespace _schedule { struct sender { template < template class Variant, template class Tuple> using value_types = Variant>; template