14c2d73ddSPatrick Williams /* 25cee9157SPatrick Williams * Copyright (c) 2021-2024 NVIDIA Corporation 34c2d73ddSPatrick Williams * 44c2d73ddSPatrick Williams * Licensed under the Apache License Version 2.0 with LLVM Exceptions 54c2d73ddSPatrick Williams * (the "License"); you may not use this file except in compliance with 64c2d73ddSPatrick Williams * the License. You may obtain a copy of the License at 74c2d73ddSPatrick Williams * 84c2d73ddSPatrick Williams * https://llvm.org/LICENSE.txt 94c2d73ddSPatrick Williams * 104c2d73ddSPatrick Williams * Unless required by applicable law or agreed to in writing, software 114c2d73ddSPatrick Williams * distributed under the License is distributed on an "AS IS" BASIS, 124c2d73ddSPatrick Williams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134c2d73ddSPatrick Williams * See the License for the specific language governing permissions and 144c2d73ddSPatrick Williams * limitations under the License. 154c2d73ddSPatrick Williams */ 164c2d73ddSPatrick Williams #pragma once 174c2d73ddSPatrick Williams 184c2d73ddSPatrick Williams #include "__concepts.hpp" 195cee9157SPatrick Williams #include "__cpo.hpp" 204c2d73ddSPatrick Williams #include "__execution_fwd.hpp" 218723a542SPatrick Williams #include "__meta.hpp" 225cee9157SPatrick Williams #include "__stop_token.hpp" 235cee9157SPatrick Williams #include "__tag_invoke.hpp" 245cee9157SPatrick Williams #include "__tuple.hpp" 254c2d73ddSPatrick Williams 268723a542SPatrick Williams #include <exception> 275cee9157SPatrick Williams #include <functional> 288723a542SPatrick Williams #include <type_traits> 294c2d73ddSPatrick Williams 304c2d73ddSPatrick Williams STDEXEC_PRAGMA_PUSH() 314c2d73ddSPatrick Williams STDEXEC_PRAGMA_IGNORE_EDG(probable_guiding_friend) 324c2d73ddSPatrick Williams STDEXEC_PRAGMA_IGNORE_EDG(type_qualifiers_ignored_on_reference) 334c2d73ddSPatrick Williams 344c2d73ddSPatrick Williams namespace stdexec 354c2d73ddSPatrick Williams { 364c2d73ddSPatrick Williams // [exec.queries.queryable] 374c2d73ddSPatrick Williams template <class T> 384c2d73ddSPatrick Williams concept queryable = destructible<T>; 394c2d73ddSPatrick Williams 404c2d73ddSPatrick Williams template <class Tag> 414c2d73ddSPatrick Williams struct __query 424c2d73ddSPatrick Williams { 434c2d73ddSPatrick Williams template <class Sig> 444c2d73ddSPatrick Williams static inline constexpr Tag (*signature)(Sig) = nullptr; 454c2d73ddSPatrick Williams }; 464c2d73ddSPatrick Williams 474c2d73ddSPatrick Williams ////////////////////////////////////////////////////////////////////////////////////////////////// 484c2d73ddSPatrick Williams // [exec.queries] 494c2d73ddSPatrick Williams namespace __queries 504c2d73ddSPatrick Williams { 515cee9157SPatrick Williams template <class _Tp> 525cee9157SPatrick Williams concept __is_bool_constant = // 535cee9157SPatrick Williams requires { // 545cee9157SPatrick Williams typename __mbool<_Tp::value>; 555cee9157SPatrick Williams }; 565cee9157SPatrick Williams 574c2d73ddSPatrick Williams struct forwarding_query_t 584c2d73ddSPatrick Williams { 594c2d73ddSPatrick Williams template <class _Query> operator ()stdexec::__queries::forwarding_query_t605cee9157SPatrick Williams consteval auto operator()(_Query __query) const noexcept -> bool 614c2d73ddSPatrick Williams { 624c2d73ddSPatrick Williams if constexpr (tag_invocable<forwarding_query_t, _Query>) 634c2d73ddSPatrick Williams { 645cee9157SPatrick Williams using __result_t = tag_invoke_result_t<forwarding_query_t, _Query>; 655cee9157SPatrick Williams // If this a integral type wrapper, unpack it and return the value. 665cee9157SPatrick Williams // Otherwise, return the result of the tag_invoke call expression. 675cee9157SPatrick Williams if constexpr (__is_bool_constant<__result_t>) 685cee9157SPatrick Williams { 695cee9157SPatrick Williams return __result_t::value; 705cee9157SPatrick Williams } 715cee9157SPatrick Williams else 725cee9157SPatrick Williams { 736e675883SPatrick Williams return tag_invoke(*this, static_cast<_Query&&>(__query)); 744c2d73ddSPatrick Williams } 755cee9157SPatrick Williams } 765cee9157SPatrick Williams else if constexpr (derived_from<_Query, forwarding_query_t>) 774c2d73ddSPatrick Williams { 784c2d73ddSPatrick Williams return true; 794c2d73ddSPatrick Williams } 804c2d73ddSPatrick Williams else 814c2d73ddSPatrick Williams { 824c2d73ddSPatrick Williams return false; 834c2d73ddSPatrick Williams } 844c2d73ddSPatrick Williams } 854c2d73ddSPatrick Williams }; 864c2d73ddSPatrick Williams 874c2d73ddSPatrick Williams struct query_or_t 884c2d73ddSPatrick Williams { 894c2d73ddSPatrick Williams template <class _Query, class _Queryable, class _Default> operator ()stdexec::__queries::query_or_t904c2d73ddSPatrick Williams constexpr auto operator()(_Query, _Queryable&&, _Default&& __default) const 914c2d73ddSPatrick Williams noexcept(__nothrow_constructible_from<_Default, _Default&&>) -> _Default 924c2d73ddSPatrick Williams { 936e675883SPatrick Williams return static_cast<_Default&&>(__default); 944c2d73ddSPatrick Williams } 954c2d73ddSPatrick Williams 964c2d73ddSPatrick Williams template <class _Query, class _Queryable, class _Default> 974c2d73ddSPatrick Williams requires __callable<_Query, _Queryable> operator ()stdexec::__queries::query_or_t984c2d73ddSPatrick Williams constexpr auto operator()(_Query __query, _Queryable&& __queryable, 994c2d73ddSPatrick Williams _Default&&) const 1004c2d73ddSPatrick Williams noexcept(__nothrow_callable<_Query, _Queryable>) 1014c2d73ddSPatrick Williams -> __call_result_t<_Query, _Queryable> 1024c2d73ddSPatrick Williams { 1036e675883SPatrick Williams return static_cast<_Query&&>(__query)( 1046e675883SPatrick Williams static_cast<_Queryable&&>(__queryable)); 1054c2d73ddSPatrick Williams } 1064c2d73ddSPatrick Williams }; 1074c2d73ddSPatrick Williams 1084c2d73ddSPatrick Williams struct execute_may_block_caller_t : __query<execute_may_block_caller_t> 1094c2d73ddSPatrick Williams { 1104c2d73ddSPatrick Williams template <class _Tp> 1114c2d73ddSPatrick Williams requires tag_invocable<execute_may_block_caller_t, __cref_t<_Tp>> operator ()stdexec::__queries::execute_may_block_caller_t1126e675883SPatrick Williams constexpr auto operator()(_Tp&& __t) const noexcept -> bool 1134c2d73ddSPatrick Williams { 1144c2d73ddSPatrick Williams static_assert( 1154c2d73ddSPatrick Williams same_as<bool, tag_invoke_result_t<execute_may_block_caller_t, 1164c2d73ddSPatrick Williams __cref_t<_Tp>>>); 1174c2d73ddSPatrick Williams static_assert( 1184c2d73ddSPatrick Williams nothrow_tag_invocable<execute_may_block_caller_t, __cref_t<_Tp>>); 1194c2d73ddSPatrick Williams return tag_invoke(execute_may_block_caller_t{}, std::as_const(__t)); 1204c2d73ddSPatrick Williams } 1214c2d73ddSPatrick Williams operator ()stdexec::__queries::execute_may_block_caller_t1226e675883SPatrick Williams constexpr auto operator()(auto&&) const noexcept -> bool 1234c2d73ddSPatrick Williams { 1244c2d73ddSPatrick Williams return true; 1254c2d73ddSPatrick Williams } 1264c2d73ddSPatrick Williams }; 1274c2d73ddSPatrick Williams 1284c2d73ddSPatrick Williams struct get_forward_progress_guarantee_t : 1294c2d73ddSPatrick Williams __query<get_forward_progress_guarantee_t> 1304c2d73ddSPatrick Williams { 1314c2d73ddSPatrick Williams template <class _Tp> 1324c2d73ddSPatrick Williams requires tag_invocable<get_forward_progress_guarantee_t, __cref_t<_Tp>> operator ()stdexec::__queries::get_forward_progress_guarantee_t1334c2d73ddSPatrick Williams constexpr auto operator()(_Tp&& __t) const noexcept( 1344c2d73ddSPatrick Williams nothrow_tag_invocable<get_forward_progress_guarantee_t, __cref_t<_Tp>>) 1355cee9157SPatrick Williams -> __decay_t<tag_invoke_result_t<get_forward_progress_guarantee_t, 1365cee9157SPatrick Williams __cref_t<_Tp>>> 1374c2d73ddSPatrick Williams { 1384c2d73ddSPatrick Williams return tag_invoke(get_forward_progress_guarantee_t{}, 1394c2d73ddSPatrick Williams std::as_const(__t)); 1404c2d73ddSPatrick Williams } 1414c2d73ddSPatrick Williams 142*06f265f6SPatrick Williams constexpr auto operator ()stdexec::__queries::get_forward_progress_guarantee_t143*06f265f6SPatrick Williams operator()(auto&&) const noexcept -> stdexec::forward_progress_guarantee 1444c2d73ddSPatrick Williams { 1454c2d73ddSPatrick Williams return stdexec::forward_progress_guarantee::weakly_parallel; 1464c2d73ddSPatrick Williams } 1474c2d73ddSPatrick Williams }; 1484c2d73ddSPatrick Williams 1494c2d73ddSPatrick Williams struct __has_algorithm_customizations_t : 1504c2d73ddSPatrick Williams __query<__has_algorithm_customizations_t> 1514c2d73ddSPatrick Williams { 1524c2d73ddSPatrick Williams template <class _Tp> 1534c2d73ddSPatrick Williams using __result_t = 1544c2d73ddSPatrick Williams tag_invoke_result_t<__has_algorithm_customizations_t, __cref_t<_Tp>>; 1554c2d73ddSPatrick Williams 1564c2d73ddSPatrick Williams template <class _Tp> 1574c2d73ddSPatrick Williams requires tag_invocable<__has_algorithm_customizations_t, __cref_t<_Tp>> operator ()stdexec::__queries::__has_algorithm_customizations_t158*06f265f6SPatrick Williams constexpr auto operator()(_Tp&&) const 159*06f265f6SPatrick Williams noexcept(noexcept(__result_t<_Tp>{})) -> __result_t<_Tp> 1604c2d73ddSPatrick Williams { 1614c2d73ddSPatrick Williams using _Boolean = tag_invoke_result_t<__has_algorithm_customizations_t, 1624c2d73ddSPatrick Williams __cref_t<_Tp>>; 1634c2d73ddSPatrick Williams static_assert(_Boolean{} 1644c2d73ddSPatrick Williams ? true 1656e675883SPatrick Williams : false); // must be contextually convertible to bool 1664c2d73ddSPatrick Williams return _Boolean{}; 1674c2d73ddSPatrick Williams } 1684c2d73ddSPatrick Williams operator ()stdexec::__queries::__has_algorithm_customizations_t1696e675883SPatrick Williams constexpr auto operator()(auto&&) const noexcept -> std::false_type 1704c2d73ddSPatrick Williams { 1714c2d73ddSPatrick Williams return {}; 1724c2d73ddSPatrick Williams } 1734c2d73ddSPatrick Williams }; 1744c2d73ddSPatrick Williams 1754c2d73ddSPatrick Williams // TODO: implement allocator concept 1764c2d73ddSPatrick Williams template <class _T0> 1774c2d73ddSPatrick Williams concept __allocator_c = true; 1784c2d73ddSPatrick Williams 1794c2d73ddSPatrick Williams struct get_scheduler_t : __query<get_scheduler_t> 1804c2d73ddSPatrick Williams { querystdexec::__queries::get_scheduler_t1815cee9157SPatrick Williams static constexpr auto query(forwarding_query_t) noexcept -> bool 1824c2d73ddSPatrick Williams { 1834c2d73ddSPatrick Williams return true; 1844c2d73ddSPatrick Williams } 1854c2d73ddSPatrick Williams 1864c2d73ddSPatrick Williams template <class _Env> 1874c2d73ddSPatrick Williams requires tag_invocable<get_scheduler_t, const _Env&> 1884c2d73ddSPatrick Williams auto operator()(const _Env& __env) const noexcept 1894c2d73ddSPatrick Williams -> tag_invoke_result_t<get_scheduler_t, const _Env&>; 1904c2d73ddSPatrick Williams 1916e675883SPatrick Williams template <class _Tag = get_scheduler_t> 1924c2d73ddSPatrick Williams auto operator()() const noexcept; 1934c2d73ddSPatrick Williams }; 1944c2d73ddSPatrick Williams 1954c2d73ddSPatrick Williams struct get_delegatee_scheduler_t : __query<get_delegatee_scheduler_t> 1964c2d73ddSPatrick Williams { querystdexec::__queries::get_delegatee_scheduler_t1975cee9157SPatrick Williams static constexpr auto query(forwarding_query_t) noexcept -> bool 1984c2d73ddSPatrick Williams { 1994c2d73ddSPatrick Williams return true; 2004c2d73ddSPatrick Williams } 2014c2d73ddSPatrick Williams 2024c2d73ddSPatrick Williams template <class _Env> 2034c2d73ddSPatrick Williams requires tag_invocable<get_delegatee_scheduler_t, const _Env&> 2044c2d73ddSPatrick Williams auto operator()(const _Env& __t) const noexcept 2054c2d73ddSPatrick Williams -> tag_invoke_result_t<get_delegatee_scheduler_t, const _Env&>; 2064c2d73ddSPatrick Williams 2076e675883SPatrick Williams template <class _Tag = get_delegatee_scheduler_t> 2084c2d73ddSPatrick Williams auto operator()() const noexcept; 2094c2d73ddSPatrick Williams }; 2104c2d73ddSPatrick Williams 2114c2d73ddSPatrick Williams struct get_allocator_t : __query<get_allocator_t> 2124c2d73ddSPatrick Williams { querystdexec::__queries::get_allocator_t2135cee9157SPatrick Williams static constexpr auto query(forwarding_query_t) noexcept -> bool 2144c2d73ddSPatrick Williams { 2154c2d73ddSPatrick Williams return true; 2164c2d73ddSPatrick Williams } 2174c2d73ddSPatrick Williams 2184c2d73ddSPatrick Williams template <class _Env> 2194c2d73ddSPatrick Williams requires tag_invocable<get_allocator_t, const _Env&> operator ()stdexec::__queries::get_allocator_t2204c2d73ddSPatrick Williams auto operator()(const _Env& __env) const noexcept 2214c2d73ddSPatrick Williams -> tag_invoke_result_t<get_allocator_t, const _Env&> 2224c2d73ddSPatrick Williams { 2234c2d73ddSPatrick Williams static_assert(nothrow_tag_invocable<get_allocator_t, const _Env&>); 2244c2d73ddSPatrick Williams static_assert( 2254c2d73ddSPatrick Williams __allocator_c<tag_invoke_result_t<get_allocator_t, const _Env&>>); 2264c2d73ddSPatrick Williams return tag_invoke(get_allocator_t{}, __env); 2274c2d73ddSPatrick Williams } 2284c2d73ddSPatrick Williams 2296e675883SPatrick Williams template <class _Tag = get_allocator_t> 2304c2d73ddSPatrick Williams auto operator()() const noexcept; 2314c2d73ddSPatrick Williams }; 2324c2d73ddSPatrick Williams 2334c2d73ddSPatrick Williams struct get_stop_token_t : __query<get_stop_token_t> 2344c2d73ddSPatrick Williams { querystdexec::__queries::get_stop_token_t2355cee9157SPatrick Williams static constexpr auto query(forwarding_query_t) noexcept -> bool 2364c2d73ddSPatrick Williams { 2374c2d73ddSPatrick Williams return true; 2384c2d73ddSPatrick Williams } 2394c2d73ddSPatrick Williams 2405cee9157SPatrick Williams template <class _Env, class _Token = never_stop_token> operator ()stdexec::__queries::get_stop_token_t2415cee9157SPatrick Williams auto operator()(const _Env&) const noexcept -> _Token 2424c2d73ddSPatrick Williams { 2434c2d73ddSPatrick Williams return {}; 2444c2d73ddSPatrick Williams } 2454c2d73ddSPatrick Williams 2465cee9157SPatrick Williams template <class _Env, class = void> 2474c2d73ddSPatrick Williams requires tag_invocable<get_stop_token_t, const _Env&> operator ()stdexec::__queries::get_stop_token_t2484c2d73ddSPatrick Williams auto operator()(const _Env& __env) const noexcept 2494c2d73ddSPatrick Williams -> tag_invoke_result_t<get_stop_token_t, const _Env&> 2504c2d73ddSPatrick Williams { 2514c2d73ddSPatrick Williams static_assert(nothrow_tag_invocable<get_stop_token_t, const _Env&>); 2525cee9157SPatrick Williams static_assert( 2535cee9157SPatrick Williams stoppable_token< 2545cee9157SPatrick Williams __decay_t<tag_invoke_result_t<get_stop_token_t, const _Env&>>>); 2554c2d73ddSPatrick Williams return tag_invoke(get_stop_token_t{}, __env); 2564c2d73ddSPatrick Williams } 2574c2d73ddSPatrick Williams 2586e675883SPatrick Williams template <class _Tag = get_stop_token_t> 2594c2d73ddSPatrick Williams auto operator()() const noexcept; 2604c2d73ddSPatrick Williams }; 2614c2d73ddSPatrick Williams 2625cee9157SPatrick Williams template <class _Queryable, class _Tag> 2634c2d73ddSPatrick Williams concept __has_completion_scheduler_for = 2644c2d73ddSPatrick Williams queryable<_Queryable> && // 2655cee9157SPatrick Williams tag_invocable<get_completion_scheduler_t<_Tag>, const _Queryable&>; 2664c2d73ddSPatrick Williams 2675cee9157SPatrick Williams template <__completion_tag _Tag> 2685cee9157SPatrick Williams struct get_completion_scheduler_t : __query<get_completion_scheduler_t<_Tag>> 2694c2d73ddSPatrick Williams { querystdexec::__queries::get_completion_scheduler_t2705cee9157SPatrick Williams static constexpr auto query(forwarding_query_t) noexcept -> bool 2714c2d73ddSPatrick Williams { 2724c2d73ddSPatrick Williams return true; 2734c2d73ddSPatrick Williams } 2744c2d73ddSPatrick Williams 2755cee9157SPatrick Williams template <__has_completion_scheduler_for<_Tag> _Queryable> 2764c2d73ddSPatrick Williams auto operator()(const _Queryable& __queryable) const noexcept 2775cee9157SPatrick Williams -> tag_invoke_result_t<get_completion_scheduler_t<_Tag>, 2784c2d73ddSPatrick Williams const _Queryable&>; 2794c2d73ddSPatrick Williams }; 2804c2d73ddSPatrick Williams 2814c2d73ddSPatrick Williams struct get_domain_t 2824c2d73ddSPatrick Williams { 2834c2d73ddSPatrick Williams template <class _Ty> 2844c2d73ddSPatrick Williams requires tag_invocable<get_domain_t, const _Ty&> operator ()stdexec::__queries::get_domain_t2854c2d73ddSPatrick Williams constexpr auto operator()(const _Ty& __ty) const noexcept 2865cee9157SPatrick Williams -> __decay_t<tag_invoke_result_t<get_domain_t, const _Ty&>> 2874c2d73ddSPatrick Williams { 2884c2d73ddSPatrick Williams static_assert(nothrow_tag_invocable<get_domain_t, const _Ty&>, 2894c2d73ddSPatrick Williams "Customizations of get_domain must be noexcept."); 2905cee9157SPatrick Williams static_assert( 2915cee9157SPatrick Williams __class<__decay_t<tag_invoke_result_t<get_domain_t, const _Ty&>>>, 2924c2d73ddSPatrick Williams "Customizations of get_domain must return a class type."); 2935cee9157SPatrick Williams return {}; 2944c2d73ddSPatrick Williams } 2954c2d73ddSPatrick Williams querystdexec::__queries::get_domain_t2965cee9157SPatrick Williams static constexpr auto query(forwarding_query_t) noexcept -> bool 2975cee9157SPatrick Williams { 2985cee9157SPatrick Williams return true; 2995cee9157SPatrick Williams } 3005cee9157SPatrick Williams }; 3015cee9157SPatrick Williams 3025cee9157SPatrick Williams struct __is_scheduler_affine_t 3035cee9157SPatrick Williams { 3045cee9157SPatrick Williams template <class _Env> operator ()stdexec::__queries::__is_scheduler_affine_t3055cee9157SPatrick Williams constexpr auto operator()(const _Env&) const noexcept 3065cee9157SPatrick Williams { 3075cee9157SPatrick Williams if constexpr (tag_invocable<__is_scheduler_affine_t, const _Env&>) 3085cee9157SPatrick Williams { 3095cee9157SPatrick Williams using _Result = 3105cee9157SPatrick Williams tag_invoke_result_t<__is_scheduler_affine_t, const _Env&>; 3115cee9157SPatrick Williams static_assert(__same_as<decltype(__v<_Result>), const bool>); 3125cee9157SPatrick Williams return _Result(); 3135cee9157SPatrick Williams } 3145cee9157SPatrick Williams else 3155cee9157SPatrick Williams { 3165cee9157SPatrick Williams return std::false_type(); 3175cee9157SPatrick Williams } 3185cee9157SPatrick Williams } 3195cee9157SPatrick Williams querystdexec::__queries::__is_scheduler_affine_t3205cee9157SPatrick Williams static constexpr auto query(forwarding_query_t) noexcept -> bool 3215cee9157SPatrick Williams { 3225cee9157SPatrick Williams return false; 3235cee9157SPatrick Williams } 3245cee9157SPatrick Williams }; 3255cee9157SPatrick Williams 3265cee9157SPatrick Williams struct __root_t 3275cee9157SPatrick Williams { 3285cee9157SPatrick Williams template <class _Env> 3295cee9157SPatrick Williams requires tag_invocable<__root_t, const _Env&> operator ()stdexec::__queries::__root_t3305cee9157SPatrick Williams constexpr auto operator()(const _Env& __env) const noexcept -> bool 3315cee9157SPatrick Williams { 3325cee9157SPatrick Williams STDEXEC_ASSERT(tag_invoke(__root_t{}, __env) == true); 3335cee9157SPatrick Williams return true; 3345cee9157SPatrick Williams } 3355cee9157SPatrick Williams querystdexec::__queries::__root_t3365cee9157SPatrick Williams static constexpr auto query(forwarding_query_t) noexcept -> bool 3375cee9157SPatrick Williams { 3385cee9157SPatrick Williams return false; 3395cee9157SPatrick Williams } 3405cee9157SPatrick Williams }; 3415cee9157SPatrick Williams 3425cee9157SPatrick Williams struct __root_env 3435cee9157SPatrick Williams { 3445cee9157SPatrick Williams using __t = __root_env; 3455cee9157SPatrick Williams using __id = __root_env; 3465cee9157SPatrick Williams STDEXEC_MEMFN_DECLstdexec::__queries::__root_env3475cee9157SPatrick Williams constexpr STDEXEC_MEMFN_DECL(auto __root)(this const __root_env&) noexcept 3486e675883SPatrick Williams -> bool 3494c2d73ddSPatrick Williams { 3504c2d73ddSPatrick Williams return true; 3514c2d73ddSPatrick Williams } 3524c2d73ddSPatrick Williams }; 3534c2d73ddSPatrick Williams } // namespace __queries 3544c2d73ddSPatrick Williams 3554c2d73ddSPatrick Williams using __queries::__has_algorithm_customizations_t; 3565cee9157SPatrick Williams using __queries::__is_scheduler_affine_t; 3575cee9157SPatrick Williams using __queries::__root_env; 3585cee9157SPatrick Williams using __queries::__root_t; 3594c2d73ddSPatrick Williams using __queries::execute_may_block_caller_t; 3604c2d73ddSPatrick Williams using __queries::forwarding_query_t; 3614c2d73ddSPatrick Williams using __queries::get_allocator_t; 3624c2d73ddSPatrick Williams using __queries::get_completion_scheduler_t; 3634c2d73ddSPatrick Williams using __queries::get_delegatee_scheduler_t; 3644c2d73ddSPatrick Williams using __queries::get_domain_t; 3654c2d73ddSPatrick Williams using __queries::get_forward_progress_guarantee_t; 3664c2d73ddSPatrick Williams using __queries::get_scheduler_t; 3674c2d73ddSPatrick Williams using __queries::get_stop_token_t; 3684c2d73ddSPatrick Williams using __queries::query_or_t; 3694c2d73ddSPatrick Williams 3704c2d73ddSPatrick Williams inline constexpr forwarding_query_t forwarding_query{}; 3714c2d73ddSPatrick Williams inline constexpr query_or_t query_or{}; // NOT TO SPEC 3724c2d73ddSPatrick Williams inline constexpr execute_may_block_caller_t execute_may_block_caller{}; 3734c2d73ddSPatrick Williams inline constexpr __has_algorithm_customizations_t 3744c2d73ddSPatrick Williams __has_algorithm_customizations{}; 3754c2d73ddSPatrick Williams inline constexpr get_forward_progress_guarantee_t 3764c2d73ddSPatrick Williams get_forward_progress_guarantee{}; 3774c2d73ddSPatrick Williams inline constexpr get_scheduler_t get_scheduler{}; 3784c2d73ddSPatrick Williams inline constexpr get_delegatee_scheduler_t get_delegatee_scheduler{}; 3794c2d73ddSPatrick Williams inline constexpr get_allocator_t get_allocator{}; 3804c2d73ddSPatrick Williams inline constexpr get_stop_token_t get_stop_token{}; 3814c2d73ddSPatrick Williams #if !STDEXEC_GCC() || defined(__OPTIMIZE_SIZE__) 3825cee9157SPatrick Williams template <__completion_tag _Tag> 3835cee9157SPatrick Williams inline constexpr get_completion_scheduler_t<_Tag> get_completion_scheduler{}; 3844c2d73ddSPatrick Williams #else 3854c2d73ddSPatrick Williams template <> 3864c2d73ddSPatrick Williams inline constexpr get_completion_scheduler_t<set_value_t> 3874c2d73ddSPatrick Williams get_completion_scheduler<set_value_t>{}; 3884c2d73ddSPatrick Williams template <> 3894c2d73ddSPatrick Williams inline constexpr get_completion_scheduler_t<set_error_t> 3904c2d73ddSPatrick Williams get_completion_scheduler<set_error_t>{}; 3914c2d73ddSPatrick Williams template <> 3924c2d73ddSPatrick Williams inline constexpr get_completion_scheduler_t<set_stopped_t> 3934c2d73ddSPatrick Williams get_completion_scheduler<set_stopped_t>{}; 3944c2d73ddSPatrick Williams #endif 3954c2d73ddSPatrick Williams 3964c2d73ddSPatrick Williams template <class _Tag> 3974c2d73ddSPatrick Williams concept __forwarding_query = forwarding_query(_Tag{}); 3984c2d73ddSPatrick Williams 3994c2d73ddSPatrick Williams inline constexpr get_domain_t get_domain{}; 4004c2d73ddSPatrick Williams 4015cee9157SPatrick Williams template <class _Env> 4025cee9157SPatrick Williams using __domain_of_t = __decay_t<__call_result_t<get_domain_t, _Env>>; 4035cee9157SPatrick Williams 4044c2d73ddSPatrick Williams template <class _Tag, class _Queryable, class _Default> 4054c2d73ddSPatrick Williams using __query_result_or_t = 4064c2d73ddSPatrick Williams __call_result_t<query_or_t, _Tag, _Queryable, _Default>; 4074c2d73ddSPatrick Williams 4084c2d73ddSPatrick Williams namespace __env 4094c2d73ddSPatrick Williams { 4101f7438aaSPatrick Williams // To be kept in sync with the promise type used in __connect_awaitable 4111f7438aaSPatrick Williams template <class _Env> 4121f7438aaSPatrick Williams struct __promise 4131f7438aaSPatrick Williams { 4141f7438aaSPatrick Williams template <class _Ty> await_transformstdexec::__env::__promise4156e675883SPatrick Williams auto await_transform(_Ty&& __value) noexcept -> _Ty&& 4161f7438aaSPatrick Williams { 4176e675883SPatrick Williams return static_cast<_Ty&&>(__value); 4181f7438aaSPatrick Williams } 4191f7438aaSPatrick Williams 4201f7438aaSPatrick Williams template <class _Ty> 4211f7438aaSPatrick Williams requires tag_invocable<as_awaitable_t, _Ty, __promise&> await_transformstdexec::__env::__promise4221f7438aaSPatrick Williams auto await_transform(_Ty&& __value) // 4231f7438aaSPatrick Williams noexcept(nothrow_tag_invocable<as_awaitable_t, _Ty, __promise&>) 4241f7438aaSPatrick Williams -> tag_invoke_result_t<as_awaitable_t, _Ty, __promise&> 4251f7438aaSPatrick Williams { 4266e675883SPatrick Williams return tag_invoke(as_awaitable, static_cast<_Ty&&>(__value), *this); 4271f7438aaSPatrick Williams } 4281f7438aaSPatrick Williams 4295cee9157SPatrick Williams auto get_env() const noexcept -> const _Env&; 4301f7438aaSPatrick Williams }; 4311f7438aaSPatrick Williams 4325cee9157SPatrick Williams template <class _Env, class _Query, class... _Args> 4335cee9157SPatrick Williams concept __queryable = // 4345cee9157SPatrick Williams tag_invocable<_Query, const _Env&, _Args...>; 4355cee9157SPatrick Williams 4365cee9157SPatrick Williams template <class _Env, class _Query, class... _Args> 4375cee9157SPatrick Williams concept __nothrow_queryable = // 4385cee9157SPatrick Williams nothrow_tag_invocable<_Query, const _Env&, _Args...>; 4395cee9157SPatrick Williams 4405cee9157SPatrick Williams template <class _Env, class _Query, class... _Args> 4415cee9157SPatrick Williams using __query_result_t = // 4425cee9157SPatrick Williams tag_invoke_result_t<_Query, const _Env&, _Args...>; 4435cee9157SPatrick Williams 4445cee9157SPatrick Williams // A singleton environment from a query/value pair 4455cee9157SPatrick Williams template <class _Query, class _Value> 4465cee9157SPatrick Williams struct prop 4475cee9157SPatrick Williams { 4485cee9157SPatrick Williams using __t = prop; 4495cee9157SPatrick Williams using __id = prop; 4505cee9157SPatrick Williams 4515cee9157SPatrick Williams STDEXEC_ATTRIBUTE((no_unique_address)) 4525cee9157SPatrick Williams _Query __query; 4535cee9157SPatrick Williams 4545cee9157SPatrick Williams STDEXEC_ATTRIBUTE((no_unique_address)) 4555cee9157SPatrick Williams _Value __value; 4565cee9157SPatrick Williams 4575cee9157SPatrick Williams STDEXEC_ATTRIBUTE((nodiscard)) querystdexec::__env::prop4585cee9157SPatrick Williams constexpr const _Value& query(_Query) const noexcept 4595cee9157SPatrick Williams { 4605cee9157SPatrick Williams return __value; 4615cee9157SPatrick Williams } 4625cee9157SPatrick Williams 4635cee9157SPatrick Williams prop& operator=(const prop&) = delete; 4645cee9157SPatrick Williams }; 4655cee9157SPatrick Williams 4665cee9157SPatrick Williams template <class _Query, class _Value> 4675cee9157SPatrick Williams prop(_Query, _Value) -> prop<_Query, std::unwrap_reference_t<_Value>>; 4685cee9157SPatrick Williams 4695cee9157SPatrick Williams // utility for joining multiple environments 4705cee9157SPatrick Williams template <class... _Envs> 4715cee9157SPatrick Williams struct env 4725cee9157SPatrick Williams { 4735cee9157SPatrick Williams using __t = env; 4745cee9157SPatrick Williams using __id = env; 4755cee9157SPatrick Williams 4765cee9157SPatrick Williams __tuple_for<_Envs...> __tup_; 4775cee9157SPatrick Williams 4785cee9157SPatrick Williams // return a reference to the first child env for which 4795cee9157SPatrick Williams // __queryable<_Envs, _Query, _Args...> is true. 4805cee9157SPatrick Williams template <class _Query, class... _Args> 4815cee9157SPatrick Williams STDEXEC_ATTRIBUTE((always_inline)) __get_1ststdexec::__env::env4825cee9157SPatrick Williams constexpr decltype(auto) __get_1st() const noexcept 4835cee9157SPatrick Williams { 4845cee9157SPatrick Williams constexpr bool __flags[] = {__queryable<_Envs, _Query, _Args...>...}; 485*06f265f6SPatrick Williams constexpr std::size_t __idx = 486*06f265f6SPatrick Williams __pos_of(__flags, __flags + sizeof...(_Envs)); 4875cee9157SPatrick Williams return __tup::get<__idx>(__tup_); 4885cee9157SPatrick Williams } 4895cee9157SPatrick Williams 4905cee9157SPatrick Williams template <class _Query, class... _Args> 4915cee9157SPatrick Williams requires(__queryable<_Envs, _Query, _Args...> || ...) 492*06f265f6SPatrick Williams STDEXEC_ATTRIBUTE((always_inline)) querystdexec::__env::env493*06f265f6SPatrick Williams constexpr decltype(auto) query(_Query __q, _Args&&... __args) const 4945cee9157SPatrick Williams noexcept(__nothrow_queryable<decltype(__get_1st<_Query, _Args...>()), 4955cee9157SPatrick Williams _Query, _Args...>) 4965cee9157SPatrick Williams { 4975cee9157SPatrick Williams return tag_invoke(__q, __get_1st<_Query, _Args...>(), 4985cee9157SPatrick Williams static_cast<_Args&&>(__args)...); 4995cee9157SPatrick Williams } 5005cee9157SPatrick Williams 5015cee9157SPatrick Williams env& operator=(const env&) = delete; 5025cee9157SPatrick Williams }; 5035cee9157SPatrick Williams 5045cee9157SPatrick Williams // specialization for two envs to avoid warnings about elided braces 5055cee9157SPatrick Williams template <class _Env0, class _Env1> 5065cee9157SPatrick Williams struct env<_Env0, _Env1> 5075cee9157SPatrick Williams { 5085cee9157SPatrick Williams using __t = env; 5095cee9157SPatrick Williams using __id = env; 5105cee9157SPatrick Williams 5115cee9157SPatrick Williams STDEXEC_ATTRIBUTE((no_unique_address)) 5125cee9157SPatrick Williams _Env0 __env0_; 5135cee9157SPatrick Williams STDEXEC_ATTRIBUTE((no_unique_address)) 5145cee9157SPatrick Williams _Env1 __env1_; 5155cee9157SPatrick Williams 5165cee9157SPatrick Williams // return a reference to the first child env for which 5175cee9157SPatrick Williams // __queryable<_Envs, _Query, _Args...> is true. 5185cee9157SPatrick Williams template <class _Query, class... _Args> 5195cee9157SPatrick Williams STDEXEC_ATTRIBUTE((always_inline)) __get_1ststdexec::__env::env5205cee9157SPatrick Williams constexpr decltype(auto) __get_1st() const noexcept 5215cee9157SPatrick Williams { 5225cee9157SPatrick Williams if constexpr (__queryable<_Env0, _Query, _Args...>) 5235cee9157SPatrick Williams { 5245cee9157SPatrick Williams return (__env0_); 5255cee9157SPatrick Williams } 5265cee9157SPatrick Williams else 5275cee9157SPatrick Williams { 5285cee9157SPatrick Williams return (__env1_); 5295cee9157SPatrick Williams } 5305cee9157SPatrick Williams } 5315cee9157SPatrick Williams 5325cee9157SPatrick Williams template <class _Query, class... _Args> 5335cee9157SPatrick Williams requires __queryable<_Env0, _Query, _Args...> || 5345cee9157SPatrick Williams __queryable<_Env1, _Query, _Args...> 535*06f265f6SPatrick Williams STDEXEC_ATTRIBUTE((always_inline)) 536*06f265f6SPatrick Williams constexpr decltype(auto) query(_Query __q, _Args&&... __args) const 5375cee9157SPatrick Williams noexcept(__nothrow_queryable<decltype(__get_1st<_Query, _Args...>()), 5385cee9157SPatrick Williams _Query, _Args...>) 5395cee9157SPatrick Williams { 5405cee9157SPatrick Williams return tag_invoke(__q, __get_1st<_Query, _Args...>(), 5415cee9157SPatrick Williams static_cast<_Args&&>(__args)...); 5425cee9157SPatrick Williams } 5435cee9157SPatrick Williams 5445cee9157SPatrick Williams env& operator=(const env&) = delete; 5455cee9157SPatrick Williams }; 5465cee9157SPatrick Williams 5475cee9157SPatrick Williams template <class... _Envs> 5485cee9157SPatrick Williams env(_Envs...) -> env<std::unwrap_reference_t<_Envs>...>; 5495cee9157SPatrick Williams 5501f7438aaSPatrick Williams template <class _Value, class _Tag, class... _Tags> 5511f7438aaSPatrick Williams struct __with 5521f7438aaSPatrick Williams { 5531f7438aaSPatrick Williams using __t = __with; 5541f7438aaSPatrick Williams using __id = __with; 5556e675883SPatrick Williams STDEXEC_ATTRIBUTE((no_unique_address)) 5566e675883SPatrick Williams _Value __value_; 5571f7438aaSPatrick Williams 5588723a542SPatrick Williams __with() = default; 5598723a542SPatrick Williams __withstdexec::__env::__with5608723a542SPatrick Williams constexpr explicit __with(_Value __value) noexcept( 5611f7438aaSPatrick Williams __nothrow_decay_copyable<_Value>) : 5626e675883SPatrick Williams __value_(static_cast<_Value&&>(__value)) 5631f7438aaSPatrick Williams {} 5641f7438aaSPatrick Williams __withstdexec::__env::__with5651f7438aaSPatrick Williams constexpr explicit __with(_Value __value, _Tag, _Tags...) noexcept( 5661f7438aaSPatrick Williams __nothrow_decay_copyable<_Value>) : 5676e675883SPatrick Williams __value_(static_cast<_Value&&>(__value)) 5681f7438aaSPatrick Williams {} 5691f7438aaSPatrick Williams 5701f7438aaSPatrick Williams template <__one_of<_Tag, _Tags...> _Key> querystdexec::__env::__with5715cee9157SPatrick Williams auto query(_Key) const noexcept -> const _Value& 5721f7438aaSPatrick Williams { 5735cee9157SPatrick Williams return __value_; 5741f7438aaSPatrick Williams } 5755cee9157SPatrick Williams 5765cee9157SPatrick Williams __with& operator=(const __with&) = delete; 5771f7438aaSPatrick Williams }; 5781f7438aaSPatrick Williams 5791f7438aaSPatrick Williams template <class _Value, class _Tag, class... _Tags> 5801f7438aaSPatrick Williams __with(_Value, _Tag, _Tags...) -> __with<_Value, _Tag, _Tags...>; 5811f7438aaSPatrick Williams 5825cee9157SPatrick Williams template <class _EnvId> 5831f7438aaSPatrick Williams struct __fwd 5841f7438aaSPatrick Williams { 5855cee9157SPatrick Williams using _Env = __cvref_t<_EnvId>; 5861f7438aaSPatrick Williams static_assert(__nothrow_move_constructible<_Env>); 5875cee9157SPatrick Williams 5885cee9157SPatrick Williams struct __t 5895cee9157SPatrick Williams { 5901f7438aaSPatrick Williams using __id = __fwd; 5916e675883SPatrick Williams STDEXEC_ATTRIBUTE((no_unique_address)) 5926e675883SPatrick Williams _Env __env_; 5931f7438aaSPatrick Williams 5945cee9157SPatrick Williams #if STDEXEC_GCC() && __GNUC__ < 12 5955cee9157SPatrick Williams using __cvref_env_t = std::add_const_t<_Env>&; 5965cee9157SPatrick Williams #else 5975cee9157SPatrick Williams using __cvref_env_t = const _Env&; 5985cee9157SPatrick Williams #endif 5995cee9157SPatrick Williams 6001f7438aaSPatrick Williams template <__forwarding_query _Tag> 6015cee9157SPatrick Williams requires tag_invocable<_Tag, __cvref_env_t> querystdexec::__env::__fwd::__t6025cee9157SPatrick Williams auto query(_Tag) const 6035cee9157SPatrick Williams noexcept(nothrow_tag_invocable<_Tag, __cvref_env_t>) 6045cee9157SPatrick Williams -> tag_invoke_result_t<_Tag, __cvref_env_t> 6051f7438aaSPatrick Williams { 6065cee9157SPatrick Williams return tag_invoke(_Tag(), __env_); 6075cee9157SPatrick Williams } 6085cee9157SPatrick Williams 6095cee9157SPatrick Williams __t& operator=(const __t&) = delete; 6105cee9157SPatrick Williams }; 6115cee9157SPatrick Williams }; 6125cee9157SPatrick Williams 6135cee9157SPatrick Williams struct __fwd_fn 6145cee9157SPatrick Williams { 6155cee9157SPatrick Williams template <class _Env> operator ()stdexec::__env::__fwd_fn6165cee9157SPatrick Williams auto operator()(_Env&& __env) const 6175cee9157SPatrick Williams { 6185cee9157SPatrick Williams return __t<__fwd<__cvref_id<_Env>>>{static_cast<_Env&&>(__env)}; 6195cee9157SPatrick Williams } 6205cee9157SPatrick Williams operator ()stdexec::__env::__fwd_fn6215cee9157SPatrick Williams auto operator()(empty_env) const -> empty_env 6225cee9157SPatrick Williams { 6235cee9157SPatrick Williams return {}; 6241f7438aaSPatrick Williams } 6251f7438aaSPatrick Williams }; 6261f7438aaSPatrick Williams 6275cee9157SPatrick Williams template <class _EnvId, class _Tag> 6285cee9157SPatrick Williams struct __without_ 6298723a542SPatrick Williams { 6305cee9157SPatrick Williams using _Env = __cvref_t<_EnvId>; 6318723a542SPatrick Williams static_assert(__nothrow_move_constructible<_Env>); 6325cee9157SPatrick Williams 6335cee9157SPatrick Williams struct __t 6345cee9157SPatrick Williams { 6358723a542SPatrick Williams using __id = __without_; 6365cee9157SPatrick Williams _Env __env_; 6378723a542SPatrick Williams 6385cee9157SPatrick Williams #if STDEXEC_GCC() && __GNUC__ < 12 6395cee9157SPatrick Williams using __cvref_env_t = std::add_const_t<_Env>&; 6405cee9157SPatrick Williams #else 6415cee9157SPatrick Williams using __cvref_env_t = const _Env&; 6425cee9157SPatrick Williams #endif 6438723a542SPatrick Williams 6445cee9157SPatrick Williams auto query(_Tag) const noexcept = delete; 6455cee9157SPatrick Williams 6465cee9157SPatrick Williams template <tag_invocable<__cvref_env_t> _Key> 6475cee9157SPatrick Williams STDEXEC_ATTRIBUTE((always_inline)) querystdexec::__env::__without_::__t648*06f265f6SPatrick Williams auto query(_Key) const noexcept( 649*06f265f6SPatrick Williams nothrow_tag_invocable<_Key, __cvref_env_t>) -> decltype(auto) 6505cee9157SPatrick Williams { 6515cee9157SPatrick Williams return tag_invoke(_Key(), __env_); 6525cee9157SPatrick Williams } 6535cee9157SPatrick Williams 6545cee9157SPatrick Williams __t& operator=(const __t&) = delete; 6555cee9157SPatrick Williams }; 6568723a542SPatrick Williams }; 6578723a542SPatrick Williams 6588723a542SPatrick Williams struct __without_fn 6598723a542SPatrick Williams { 6605cee9157SPatrick Williams template <class _Env, class _Tag> operator ()stdexec::__env::__without_fn661*06f265f6SPatrick Williams constexpr auto operator()(_Env&& __env, 662*06f265f6SPatrick Williams _Tag) const noexcept -> decltype(auto) 6638723a542SPatrick Williams { 6645cee9157SPatrick Williams if constexpr (tag_invocable<_Tag, _Env>) 6658723a542SPatrick Williams { 6665cee9157SPatrick Williams using _Without = __t<__without_<__cvref_id<_Env>, _Tag>>; 6675cee9157SPatrick Williams return _Without{static_cast<_Env&&>(__env)}; 6688723a542SPatrick Williams } 6698723a542SPatrick Williams else 6708723a542SPatrick Williams { 6716e675883SPatrick Williams return static_cast<_Env>(static_cast<_Env&&>(__env)); 6728723a542SPatrick Williams } 6738723a542SPatrick Williams } 6748723a542SPatrick Williams }; 6758723a542SPatrick Williams 6768723a542SPatrick Williams inline constexpr __without_fn __without{}; 6778723a542SPatrick Williams 6788723a542SPatrick Williams template <class _Env, class _Tag, class... _Tags> 6798723a542SPatrick Williams using __without_t = __result_of<__without, _Env, _Tag, _Tags...>; 6808723a542SPatrick Williams 6811f7438aaSPatrick Williams template <__nothrow_move_constructible _Fun> 6821f7438aaSPatrick Williams struct __from 6831f7438aaSPatrick Williams { 6841f7438aaSPatrick Williams using __t = __from; 6851f7438aaSPatrick Williams using __id = __from; 6866e675883SPatrick Williams STDEXEC_ATTRIBUTE((no_unique_address)) 6876e675883SPatrick Williams _Fun __fun_; 6881f7438aaSPatrick Williams 6891f7438aaSPatrick Williams template <class _Tag> 6901f7438aaSPatrick Williams requires __callable<const _Fun&, _Tag> querystdexec::__env::__from6915cee9157SPatrick Williams auto query(_Tag) const noexcept(__nothrow_callable<const _Fun&, _Tag>) 6921f7438aaSPatrick Williams -> __call_result_t<const _Fun&, _Tag> 6931f7438aaSPatrick Williams { 6945cee9157SPatrick Williams return __fun_(_Tag()); 6951f7438aaSPatrick Williams } 6965cee9157SPatrick Williams 6975cee9157SPatrick Williams __from& operator=(const __from&) = delete; 6981f7438aaSPatrick Williams }; 6991f7438aaSPatrick Williams 7001f7438aaSPatrick Williams template <class _Fun> 7011f7438aaSPatrick Williams __from(_Fun) -> __from<_Fun>; 7021f7438aaSPatrick Williams 7031f7438aaSPatrick Williams struct __join_fn 7041f7438aaSPatrick Williams { operator ()stdexec::__env::__join_fn7055cee9157SPatrick Williams auto operator()(empty_env, empty_env) const noexcept -> empty_env 7061f7438aaSPatrick Williams { 7071f7438aaSPatrick Williams return {}; 7081f7438aaSPatrick Williams } 7091f7438aaSPatrick Williams 7101f7438aaSPatrick Williams template <class _Env> operator ()stdexec::__env::__join_fn7115cee9157SPatrick Williams auto operator()(_Env&& __env, empty_env = {}) const noexcept -> _Env 7121f7438aaSPatrick Williams { 7136e675883SPatrick Williams return static_cast<_Env&&>(__env); 7141f7438aaSPatrick Williams } 7151f7438aaSPatrick Williams 7161f7438aaSPatrick Williams template <class _Env> operator ()stdexec::__env::__join_fn7175cee9157SPatrick Williams auto operator()(empty_env, _Env&& __env) const noexcept -> decltype(auto) 7181f7438aaSPatrick Williams { 7195cee9157SPatrick Williams return __fwd_fn()(static_cast<_Env&&>(__env)); 7201f7438aaSPatrick Williams } 7211f7438aaSPatrick Williams 7225cee9157SPatrick Williams template <class _First, class _Second> operator ()stdexec::__env::__join_fn7235cee9157SPatrick Williams auto operator()(_First&& __first, _Second&& __second) const noexcept 7245cee9157SPatrick Williams -> env<_First, __call_result_t<__fwd_fn, _Second>> 7251f7438aaSPatrick Williams { 7265cee9157SPatrick Williams return {static_cast<_First&&>(__first), 7275cee9157SPatrick Williams __fwd_fn()(static_cast<_Second&&>(__second))}; 7281f7438aaSPatrick Williams } 7291f7438aaSPatrick Williams }; 7301f7438aaSPatrick Williams 7311f7438aaSPatrick Williams inline constexpr __join_fn __join{}; 7321f7438aaSPatrick Williams 7335cee9157SPatrick Williams template <class _First, class... _Second> 7345cee9157SPatrick Williams using __join_t = __result_of<__join, _First, _Second...>; 7355cee9157SPatrick Williams 7365cee9157SPatrick Williams struct __as_root_env_fn 7375cee9157SPatrick Williams { 7385cee9157SPatrick Williams template <class _Env> operator ()stdexec::__env::__as_root_env_fn7395cee9157SPatrick Williams constexpr auto operator()(_Env __env) const noexcept 7405cee9157SPatrick Williams -> __join_t<__root_env, std::unwrap_reference_t<_Env>> 7415cee9157SPatrick Williams { 7425cee9157SPatrick Williams return __join(__root_env{}, 7435cee9157SPatrick Williams static_cast<std::unwrap_reference_t<_Env>&&>(__env)); 7445cee9157SPatrick Williams } 7455cee9157SPatrick Williams }; 7465cee9157SPatrick Williams 7475cee9157SPatrick Williams inline constexpr __as_root_env_fn __as_root_env{}; 7485cee9157SPatrick Williams 7495cee9157SPatrick Williams template <class _Env> 7505cee9157SPatrick Williams using __as_root_env_t = __result_of<__as_root_env, _Env>; 7514c2d73ddSPatrick Williams } // namespace __env 7524c2d73ddSPatrick Williams 7535cee9157SPatrick Williams using __env::env; 7545cee9157SPatrick Williams using __env::prop; 7555cee9157SPatrick Williams using empty_env = env<>; 7565cee9157SPatrick Williams 7575cee9157SPatrick Williams ///////////////////////////////////////////////////////////////////////////// 7585cee9157SPatrick Williams namespace __get_env 7595cee9157SPatrick Williams { 7605cee9157SPatrick Williams // For getting an execution environment from a receiver or the attributes from a 7615cee9157SPatrick Williams // sender. 7625cee9157SPatrick Williams struct get_env_t 7635cee9157SPatrick Williams { 7645cee9157SPatrick Williams template <__same_as<get_env_t> _Self, class _EnvProvider> 7655cee9157SPatrick Williams STDEXEC_ATTRIBUTE((always_inline)) tag_invoke(_Self,const _EnvProvider & __env_provider)7665cee9157SPatrick Williams friend auto tag_invoke(_Self, const _EnvProvider& __env_provider) noexcept 7675cee9157SPatrick Williams -> decltype(__env_provider.get_env()) 7685cee9157SPatrick Williams { 7695cee9157SPatrick Williams static_assert(noexcept(__env_provider.get_env()), 7705cee9157SPatrick Williams "get_env() members must be noexcept"); 7715cee9157SPatrick Williams return __env_provider.get_env(); 7725cee9157SPatrick Williams } 7735cee9157SPatrick Williams 7745cee9157SPatrick Williams template <class _EnvProvider> 7755cee9157SPatrick Williams requires tag_invocable<get_env_t, const _EnvProvider&> 776*06f265f6SPatrick Williams STDEXEC_ATTRIBUTE((always_inline)) operator ()stdexec::__get_env::get_env_t777*06f265f6SPatrick Williams constexpr auto operator()(const _EnvProvider& __env_provider) const noexcept 7785cee9157SPatrick Williams -> tag_invoke_result_t<get_env_t, const _EnvProvider&> 7795cee9157SPatrick Williams { 7805cee9157SPatrick Williams static_assert( 7815cee9157SPatrick Williams queryable<tag_invoke_result_t<get_env_t, const _EnvProvider&>>); 7825cee9157SPatrick Williams static_assert(nothrow_tag_invocable<get_env_t, const _EnvProvider&>); 7835cee9157SPatrick Williams return tag_invoke(*this, __env_provider); 7845cee9157SPatrick Williams } 7855cee9157SPatrick Williams 7865cee9157SPatrick Williams template <class _EnvProvider> operator ()stdexec::__get_env::get_env_t7875cee9157SPatrick Williams constexpr auto operator()(const _EnvProvider&) const noexcept -> empty_env 7885cee9157SPatrick Williams { 7895cee9157SPatrick Williams return {}; 7905cee9157SPatrick Williams } 7915cee9157SPatrick Williams }; 7925cee9157SPatrick Williams } // namespace __get_env 7935cee9157SPatrick Williams 7945cee9157SPatrick Williams using __get_env::get_env_t; 7951f7438aaSPatrick Williams inline constexpr get_env_t get_env{}; 7964c2d73ddSPatrick Williams 7974c2d73ddSPatrick Williams template <class _EnvProvider> 7984c2d73ddSPatrick Williams concept environment_provider = // 7994c2d73ddSPatrick Williams requires(_EnvProvider& __ep) { 800*06f265f6SPatrick Williams { get_env(std::as_const(__ep)) } -> queryable; 8014c2d73ddSPatrick Williams }; 8025cee9157SPatrick Williams 8035cee9157SPatrick Williams using __env::__as_root_env; 8045cee9157SPatrick Williams using __env::__as_root_env_t; 8055cee9157SPatrick Williams 8065cee9157SPatrick Williams template <class _Env> 8075cee9157SPatrick Williams concept __is_root_env = requires(_Env&& __env) { 808*06f265f6SPatrick Williams { __root_t{}(__env) } -> same_as<bool>; 8095cee9157SPatrick Williams }; 8105cee9157SPatrick Williams 8115cee9157SPatrick Williams template <class _Sender> 8125cee9157SPatrick Williams concept __is_scheduler_affine = // 8135cee9157SPatrick Williams requires { 8145cee9157SPatrick Williams requires __v< 8155cee9157SPatrick Williams __call_result_t<__is_scheduler_affine_t, env_of_t<_Sender>>>; 8165cee9157SPatrick Williams }; 8174c2d73ddSPatrick Williams } // namespace stdexec 8184c2d73ddSPatrick Williams 8194c2d73ddSPatrick Williams STDEXEC_PRAGMA_POP() 820