diff --git a/include/exec/any_sender_of.hpp b/include/exec/any_sender_of.hpp index 645f094a6..09e12efef 100644 --- a/include/exec/any_sender_of.hpp +++ b/include/exec/any_sender_of.hpp @@ -855,7 +855,7 @@ namespace exec { STDEXEC::inplace_stop_source __stop_source_{}; using __stop_callback = typename STDEXEC::stop_token_of_t< STDEXEC::env_of_t<_Receiver> - >::template callback_type<__forward_stop_request>; + >::template callback_type; std::optional<__stop_callback> __on_stop_{}; }; diff --git a/include/exec/start_now.hpp b/include/exec/start_now.hpp index 76f4afc2c..6dd850f2f 100644 --- a/include/exec/start_now.hpp +++ b/include/exec/start_now.hpp @@ -188,7 +188,7 @@ namespace exec { struct start_now_t { template < - STDEXEC::queryable _Env, + STDEXEC::__queryable _Env, exec::__scope::__async_scope _AsyncScope, STDEXEC::sender... _Sender > diff --git a/include/exec/task.hpp b/include/exec/task.hpp index baf07645d..bd59e0dce 100644 --- a/include/exec/task.hpp +++ b/include/exec/task.hpp @@ -334,7 +334,7 @@ namespace exec { private: using __scheduler_t = - __query_result_or_t; + __call_result_or_t; struct __final_awaitable { static constexpr auto await_ready() noexcept -> bool { diff --git a/include/stdexec/__detail/__completion_behavior.hpp b/include/stdexec/__detail/__completion_behavior.hpp index c05d1fd15..69dd05ddc 100644 --- a/include/stdexec/__detail/__completion_behavior.hpp +++ b/include/stdexec/__detail/__completion_behavior.hpp @@ -95,50 +95,45 @@ namespace STDEXEC { ////////////////////////////////////////////////////////////////////////////////////////// // get_completion_behavior: A sender can define this attribute to describe the sender's // completion behavior - namespace __queries { - template <__completion_tag _Tag> - struct get_completion_behavior_t { - private: - template - STDEXEC_ATTRIBUTE(always_inline, host, device) - static constexpr auto __validate() noexcept { - using __result_t = __member_query_result_t<_Attrs, get_completion_behavior_t, _Env...>; - static_assert( - __nothrow_member_queryable_with<_Attrs, get_completion_behavior_t, _Env...>, - "The get_completion_behavior query must be noexcept."); - static_assert( - __std::convertible_to<__result_t, completion_behavior::behavior>, - "The get_completion_behavior query must return one of the static member variables in " - "execution::completion_behavior."); - return __result_t{}; - } + template <__completion_tag _Tag> + struct get_completion_behavior_t { + private: + template + STDEXEC_ATTRIBUTE(always_inline, host, device) + static constexpr auto __validate() noexcept { + using __result_t = __member_query_result_t<_Attrs, get_completion_behavior_t, _Env...>; + static_assert( + __nothrow_member_queryable_with<_Attrs, get_completion_behavior_t, _Env...>, + "The get_completion_behavior query must be noexcept."); + static_assert( + __std::convertible_to<__result_t, completion_behavior::behavior>, + "The get_completion_behavior query must return one of the static member variables in " + "execution::completion_behavior."); + return __result_t{}; + } - public: - template - static inline constexpr get_completion_behavior_t (*signature)(_Sig) = nullptr; + public: + template + static inline constexpr get_completion_behavior_t (*signature)(_Sig) = nullptr; - template - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - constexpr auto operator()(const _Attrs&, const _Env&...) const noexcept { - if constexpr ( - __member_queryable_with, _Env...>) { - return __validate<_Attrs, _Env...>(); - } else if constexpr (__member_queryable_with< - const _Attrs&, - get_completion_behavior_t<_Tag> - >) { - return __validate<_Attrs>(); - } else { - return completion_behavior::unknown; - } + template + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + constexpr auto operator()(const _Attrs&, const _Env&...) const noexcept { + if constexpr ( + __member_queryable_with, _Env...>) { + return __validate<_Attrs, _Env...>(); + } else if constexpr (__member_queryable_with>) { + return __validate<_Attrs>(); + } else { + return completion_behavior::unknown; } + } - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - static constexpr auto query(forwarding_query_t) noexcept -> bool { - return true; - } - }; - } // namespace __queries + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + static constexpr auto query(forwarding_query_t) noexcept -> bool { + return true; + } + }; [[deprecated("use STDEXEC::completion_behavior::weakest instead")]] inline constexpr const auto& min = completion_behavior::weakest; diff --git a/include/stdexec/__detail/__config.hpp b/include/stdexec/__detail/__config.hpp index 0e40c1a00..1edb0b7fd 100644 --- a/include/stdexec/__detail/__config.hpp +++ b/include/stdexec/__detail/__config.hpp @@ -179,7 +179,9 @@ #endif STDEXEC_NAMESPACE_STD_BEGIN -namespace execution { +namespace execution::system_context_replaceability { +} +namespace this_thread { } STDEXEC_NAMESPACE_STD_END @@ -207,6 +209,18 @@ STDEXEC_NAMESPACE_STD_END # error stdexec cannot be defined directly in namespace std, but a namespace nested inside std is allowed. #endif +// clang-format off +#if STDEXEC_NAMESPACE_IS_WITHIN_STD() +# define STDEXEC_P2300_NAMESPACE_BEGIN(...) STDEXEC_NAMESPACE_STD_BEGIN __VA_OPT__(namespace __VA_ARGS__ {) +# define STDEXEC_P2300_NAMESPACE_END(...) __VA_OPT__(}) STDEXEC_NAMESPACE_STD_END +# define STDEXEC_P2300_DEPRECATED_SYMBOL(...) using __VA_ARGS__; +#else +# define STDEXEC_P2300_NAMESPACE_BEGIN(...) namespace STDEXEC { +# define STDEXEC_P2300_NAMESPACE_END(...) } +# define STDEXEC_P2300_DEPRECATED_SYMBOL(...) +#endif +// clang-format on + //////////////////////////////////////////////////////////////////////////////////////////////////// #if __cpp_impl_coroutine >= 2019'02L && __cpp_lib_coroutine >= 2019'02L # include // IWYU pragma: keep diff --git a/include/stdexec/__detail/__debug.hpp b/include/stdexec/__detail/__debug.hpp index b9a889f44..2846d69ec 100644 --- a/include/stdexec/__detail/__debug.hpp +++ b/include/stdexec/__detail/__debug.hpp @@ -29,13 +29,11 @@ namespace STDEXEC { ///////////////////////////////////////////////////////////////////////////// // Some utilities for debugging senders - namespace __queries { - struct __debug_env_t : __query<__debug_env_t> { - static constexpr auto query(forwarding_query_t) noexcept -> bool { - return true; - } - }; - } // namespace __queries + struct __debug_env_t : __query<__debug_env_t> { + static constexpr auto query(forwarding_query_t) noexcept -> bool { + return true; + } + }; namespace __debug { struct _COMPLETION_SIGNATURES_MISMATCH_ { }; @@ -59,7 +57,7 @@ namespace STDEXEC { } template - using __env_t = env, _Env>; + using __env_t = env, _Env>; template struct __receiver { diff --git a/include/stdexec/__detail/__domain.hpp b/include/stdexec/__detail/__domain.hpp index 221a2b714..acb785ed3 100644 --- a/include/stdexec/__detail/__domain.hpp +++ b/include/stdexec/__detail/__domain.hpp @@ -204,206 +204,201 @@ namespace STDEXEC { } } // namespace __detail - namespace __queries { - //! @brief A wrapper around an environment that hides a set of queries. - template - struct __hide_query { - constexpr explicit __hide_query(_Env&& __env, _Queries...) noexcept - : __env_{static_cast<_Env&&>(__env)} { - } + //! @brief A wrapper around an environment that hides a set of queries. + template + struct __hide_query { + constexpr explicit __hide_query(_Env&& __env, _Queries...) noexcept + : __env_{static_cast<_Env&&>(__env)} { + } - template <__none_of<_Queries...> _Query, class... _As> - requires __queryable_with<_Env, _Query, _As...> - constexpr auto operator()(_Query, _As&&... __as) const - noexcept(__nothrow_queryable_with<_Env, _Query, _As...>) - -> __query_result_t<_Env, _Query, _As...> { - return __query<_Query>()(__env_, static_cast<_As&&>(__as)...); - } + template <__none_of<_Queries...> _Query, class... _As> + requires __queryable_with<_Env, _Query, _As...> + constexpr auto operator()(_Query, _As&&... __as) const + noexcept(__nothrow_queryable_with<_Env, _Query, _As...>) + -> __query_result_t<_Env, _Query, _As...> { + return __query<_Query>()(__env_, static_cast<_As&&>(__as)...); + } - private: - _Env __env_; - }; + private: + _Env __env_; + }; - template - STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE - __hide_query(_Env&&, _Queries...) -> __hide_query<_Env, _Queries...>; + template + STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE + __hide_query(_Env&&, _Queries...) -> __hide_query<_Env, _Queries...>; - //! @brief A wrapper around an environment that hides the get_scheduler and get_domain - //! queries. - template - struct __hide_scheduler : __hide_query<_Env, get_scheduler_t, get_domain_t> { - constexpr explicit __hide_scheduler(_Env&& __env) noexcept - : __hide_query<_Env, get_scheduler_t, get_domain_t>{static_cast<_Env&&>(__env), {}, {}} { - } - }; - - template - STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE __hide_scheduler(_Env&&) -> __hide_scheduler<_Env>; + //! @brief A wrapper around an environment that hides the get_scheduler and get_domain + //! queries. + template + struct __hide_scheduler : __hide_query<_Env, get_scheduler_t, get_domain_t> { + constexpr explicit __hide_scheduler(_Env&& __env) noexcept + : __hide_query<_Env, get_scheduler_t, get_domain_t>{static_cast<_Env&&>(__env), {}, {}} { + } + }; - ////////////////////////////////////////////////////////////////////////////////////////// - //! @brief A query type for asking a sender's attributes for the domain on which that - //! sender will complete. As with @c get_domain, it is used in tag dispatching to find a - //! custom implementation of a sender algorithm. - //! - //! @tparam _Tag one of set_value_t, set_error_t, or set_stopped_t - template - struct get_completion_domain_t { - template - static inline constexpr get_completion_domain_t<_Tag> (*signature)(Sig) = nullptr; - - // This function object reads the completion domain from an attribute object or a - // scheduler, accounting for the fact that the query member function may or may not - // accept an environment. - struct __read_query_t { - template - requires __queryable_with<_Attrs, get_completion_domain_t> - constexpr auto operator()(const _Attrs&, __ignore = {}) const noexcept { - return __decay_t<__query_result_t<_Attrs, get_completion_domain_t>>{}; - } + template + STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE __hide_scheduler(_Env&&) -> __hide_scheduler<_Env>; - template - requires __queryable_with<_Attrs, get_completion_domain_t, const _Env&> - constexpr auto operator()(const _Attrs&, const _Env&) const noexcept { - return __decay_t<__query_result_t<_Attrs, get_completion_domain_t, const _Env&>>{}; - } - }; + ////////////////////////////////////////////////////////////////////////////////////////// + //! @brief A query type for asking a sender's attributes for the domain on which that + //! sender will complete. As with @c get_domain, it is used in tag dispatching to find a + //! custom implementation of a sender algorithm. + //! + //! @tparam _Tag one of set_value_t, set_error_t, or set_stopped_t + template + struct get_completion_domain_t { + template + static inline constexpr get_completion_domain_t<_Tag> (*signature)(Sig) = nullptr; + + // This function object reads the completion domain from an attribute object or a + // scheduler, accounting for the fact that the query member function may or may not + // accept an environment. + struct __read_query_t { + template + requires __queryable_with<_Attrs, get_completion_domain_t> + constexpr auto operator()(const _Attrs&, __ignore = {}) const noexcept { + return __decay_t<__query_result_t<_Attrs, get_completion_domain_t>>{}; + } - private: - template - static consteval auto __check_domain_(_Domain) noexcept { - static_assert( - __same_as<_Domain, __detail::__scheduler_domain_t<_Sch, const _Env&...>>, - "the sender claims to complete on a domain that is not the domain of its completion " - "scheduler"); + template + requires __queryable_with<_Attrs, get_completion_domain_t, const _Env&> + constexpr auto operator()(const _Attrs&, const _Env&) const noexcept { + return __decay_t<__query_result_t<_Attrs, get_completion_domain_t, const _Env&>>{}; } + }; + + private: + template + static consteval auto __check_domain_(_Domain) noexcept { + static_assert( + __same_as<_Domain, __detail::__scheduler_domain_t<_Sch, const _Env&...>>, + "the sender claims to complete on a domain that is not the domain of its completion " + "scheduler"); + } - template - static consteval auto __check_domain(_Domain) noexcept -> _Domain { - // Sanity check: if a completion scheduler can be determined from the attributes - // (not the environment), then its domain must match the domain returned by the attributes. - if constexpr (!__same_as<_Tag, void>) { - if constexpr (__callable, const _Attrs&, const _Env&...>) { - using __sch_t = - __call_result_t, const _Attrs&, const _Env&...>; - // Skip check if the "scheduler" is the same as the domain or the attributes - // (this can happen with __prop_like which answers any query with the same type) - if constexpr (!__same_as<__sch_t, _Attrs>) { - __check_domain_<__sch_t, _Env...>(_Domain{}); - } + template + static consteval auto __check_domain(_Domain) noexcept -> _Domain { + // Sanity check: if a completion scheduler can be determined from the attributes + // (not the environment), then its domain must match the domain returned by the attributes. + if constexpr (!__same_as<_Tag, void>) { + if constexpr (__callable, const _Attrs&, const _Env&...>) { + using __sch_t = + __call_result_t, const _Attrs&, const _Env&...>; + // Skip check if the "scheduler" is the same as the domain or the attributes + // (this can happen with __prop_like which answers any query with the same type) + if constexpr (!__same_as<__sch_t, _Attrs>) { + __check_domain_<__sch_t, _Env...>(_Domain{}); } } - return {}; } + return {}; + } - template - static constexpr auto __get_domain() noexcept { - // If __attrs has a completion domain, then return it: - if constexpr (__callable<__read_query_t, const _Attrs&, const _Env&...>) { - using __domain_t = __call_result_t<__read_query_t, const _Attrs&, const _Env&...>; + template + static constexpr auto __get_domain() noexcept { + // If __attrs has a completion domain, then return it: + if constexpr (__callable<__read_query_t, const _Attrs&, const _Env&...>) { + using __domain_t = __call_result_t<__read_query_t, const _Attrs&, const _Env&...>; + return __check_domain<_Attrs, _Env...>(__domain_t{}); + // Otherwise, if _Tag is void, fall back to querying for the set_value_t completion domain: + } else if constexpr (__same_as<_Tag, void>) { + if constexpr ( + __callable, const _Attrs&, const _Env&...>) { + using __domain_t = + __call_result_t, const _Attrs&, const _Env&...>; return __check_domain<_Attrs, _Env...>(__domain_t{}); - // Otherwise, if _Tag is void, fall back to querying for the set_value_t completion domain: - } else if constexpr (__same_as<_Tag, void>) { - if constexpr ( - __callable, const _Attrs&, const _Env&...>) { - using __domain_t = - __call_result_t, const _Attrs&, const _Env&...>; - return __check_domain<_Attrs, _Env...>(__domain_t{}); - } else { - return void(); - } + } else { + return void(); } - // Otherwise, if __attrs has a completion scheduler, we can ask that scheduler for its - // completion domain. - else if constexpr ( - __callable, const _Attrs&, const _Env&...>) { - using __sch_t = - __call_result_t, const _Attrs&, const _Env&...>; - using X [[maybe_unused]] = decltype(__declval<__sch_t>().schedule()); - using __read_query_t = typename get_completion_domain_t::__read_query_t; - - if constexpr (__callable<__read_query_t, __sch_t, const _Env&...>) { - using __domain_t = __call_result_t<__read_query_t, __sch_t, const _Env&...>; - return __domain_t{}; - } - // Otherwise, if the scheduler's sender indicates that it completes inline, we can ask - // the environment for its domain. - else if constexpr ( - __completes_inline<_Tag, env_of_t<__call_result_t>, _Env...> - && __callable) { - return __call_result_t{}; - } - // Otherwise, if we are asking "late" (with an environment), return the default_domain - else if constexpr (sizeof...(_Env) != 0) { - return default_domain{}; - } + } + // Otherwise, if __attrs has a completion scheduler, we can ask that scheduler for its + // completion domain. + else if constexpr ( + __callable, const _Attrs&, const _Env&...>) { + using __sch_t = + __call_result_t, const _Attrs&, const _Env&...>; + using X [[maybe_unused]] = decltype(__declval<__sch_t>().schedule()); + using __read_query_t = typename get_completion_domain_t::__read_query_t; + + if constexpr (__callable<__read_query_t, __sch_t, const _Env&...>) { + using __domain_t = __call_result_t<__read_query_t, __sch_t, const _Env&...>; + return __domain_t{}; } - // Otherwise, if the attributes indicates that the sender completes inline, we can ask + // Otherwise, if the scheduler's sender indicates that it completes inline, we can ask // the environment for its domain. else if constexpr ( - __completes_inline<_Tag, _Attrs, _Env...> && __callable) { + __completes_inline<_Tag, env_of_t<__call_result_t>, _Env...> + && __callable) { return __call_result_t{}; } // Otherwise, if we are asking "late" (with an environment), return the default_domain else if constexpr (sizeof...(_Env) != 0) { return default_domain{}; } - // Otherwise, no completion domain can be determined. Return void. } + // Otherwise, if the attributes indicates that the sender completes inline, we can ask + // the environment for its domain. + else if constexpr ( + __completes_inline<_Tag, _Attrs, _Env...> && __callable) { + return __call_result_t{}; + } + // Otherwise, if we are asking "late" (with an environment), return the default_domain + else if constexpr (sizeof...(_Env) != 0) { + return default_domain{}; + } + // Otherwise, no completion domain can be determined. Return void. + } - template - using __result_t = __unless_one_of_t()), void>; + template + using __result_t = __unless_one_of_t()), void>; - public: - template - constexpr auto - operator()(const _Attrs&, const _Env&...) const noexcept -> __result_t<_Attrs, _Env...> { - return {}; - } + public: + template + constexpr auto + operator()(const _Attrs&, const _Env&...) const noexcept -> __result_t<_Attrs, _Env...> { + return {}; + } - static constexpr auto query(forwarding_query_t) noexcept -> bool { - return true; - } - }; + static constexpr auto query(forwarding_query_t) noexcept -> bool { + return true; + } + }; - struct get_domain_t { - template - static inline constexpr get_domain_t (*signature)(_Sig) = nullptr; - - // Query with a .query member function: - template - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - constexpr auto operator()(const _Env&) const noexcept -> auto { - if constexpr (__member_queryable_with) { - return __decay_t<__member_query_result_t<_Env, get_domain_t>>{}; - } else if constexpr (__callable) { - using __sch_t = __call_result_t; - using __env_t = __hide_scheduler; - using __cmpl_sch_t = - __call_result_t, __sch_t, __env_t>; - return __detail::__scheduler_domain_t<__cmpl_sch_t, __env_t>{}; - } else { - return default_domain{}; - } - } + struct get_domain_t { + template + static inline constexpr get_domain_t (*signature)(_Sig) = nullptr; - // Query with tag_invoke (legacy): - template - requires __tag_invocable - [[deprecated("use a query member function instead of tag_invoke for queries")]] - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) // - constexpr auto operator()(const _Env&) const noexcept { - return __decay_t<__tag_invoke_result_t>{}; + // Query with a .query member function: + template + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + constexpr auto operator()(const _Env&) const noexcept -> auto { + if constexpr (__member_queryable_with) { + return __decay_t<__member_query_result_t<_Env, get_domain_t>>{}; + } else if constexpr (__callable) { + using __sch_t = __call_result_t; + using __env_t = __hide_scheduler; + using __cmpl_sch_t = + __call_result_t, __sch_t, __env_t>; + return __detail::__scheduler_domain_t<__cmpl_sch_t, __env_t>{}; + } else { + return default_domain{}; } + } - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - static consteval auto query(forwarding_query_t) noexcept -> bool { - return true; - } - }; - } // namespace __queries + // Query with tag_invoke (legacy): + template + requires __tag_invocable + [[deprecated("use a query member function instead of tag_invoke for queries")]] + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) // + constexpr auto operator()(const _Env&) const noexcept { + return __decay_t<__tag_invoke_result_t>{}; + } - using __queries::get_completion_domain_t; - using __queries::get_domain_t; + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + static consteval auto query(forwarding_query_t) noexcept -> bool { + return true; + } + }; #if !STDEXEC_GCC() || defined(__OPTIMIZE_SIZE__) template diff --git a/include/stdexec/__detail/__env.hpp b/include/stdexec/__detail/__env.hpp index 7496ba32d..2993297c5 100644 --- a/include/stdexec/__detail/__env.hpp +++ b/include/stdexec/__detail/__env.hpp @@ -261,13 +261,8 @@ namespace STDEXEC { using __get_env::get_env_t; inline constexpr get_env_t get_env{}; - // template - // concept environment_provider = requires(_EnvProvider& __ep) { - // { get_env(std::as_const(__ep)) } -> queryable; - // }; - template - concept environment_provider = __minvocable_q<__call_result_t, get_env_t, const _EnvProvider&>; + concept __environment_provider = __minvocable_q<__call_result_t, get_env_t, const _EnvProvider&>; } // namespace STDEXEC diff --git a/include/stdexec/__detail/__execution_fwd.hpp b/include/stdexec/__detail/__execution_fwd.hpp index c6be96ab0..21003ad2a 100644 --- a/include/stdexec/__detail/__execution_fwd.hpp +++ b/include/stdexec/__detail/__execution_fwd.hpp @@ -119,44 +119,24 @@ namespace STDEXEC { weakly_parallel }; - namespace __queries { - struct forwarding_query_t; - struct execute_may_block_caller_t; - struct get_forward_progress_guarantee_t; - struct get_scheduler_t; - struct get_delegation_scheduler_t; - struct get_allocator_t; - struct get_stop_token_t; - template <__completion_tag _CPO> - struct get_completion_scheduler_t; - template - struct get_completion_domain_t; - template <__completion_tag _CPO> - struct get_completion_behavior_t; - struct get_domain_t; - - struct __debug_env_t; - } // namespace __queries - - using __queries::forwarding_query_t; - using __queries::execute_may_block_caller_t; - using __queries::get_forward_progress_guarantee_t; - using __queries::get_allocator_t; - using __queries::get_scheduler_t; - using __queries::get_delegation_scheduler_t; - using __queries::get_stop_token_t; - using __queries::get_completion_scheduler_t; - using __queries::get_completion_domain_t; - using __queries::get_completion_behavior_t; - using __queries::get_domain_t; - - extern const forwarding_query_t forwarding_query; - extern const execute_may_block_caller_t execute_may_block_caller; + struct __execute_may_block_caller_t; + struct get_forward_progress_guarantee_t; + struct get_scheduler_t; + struct get_delegation_scheduler_t; + template <__completion_tag _CPO> + struct get_completion_scheduler_t; + template + struct get_completion_domain_t; + template <__completion_tag _CPO> + struct get_completion_behavior_t; + struct get_domain_t; + + struct __debug_env_t; + + extern const __execute_may_block_caller_t execute_may_block_caller; extern const get_forward_progress_guarantee_t get_forward_progress_guarantee; extern const get_scheduler_t get_scheduler; extern const get_delegation_scheduler_t get_delegation_scheduler; - extern const get_allocator_t get_allocator; - extern const get_stop_token_t get_stop_token; template <__completion_tag _CPO> extern const get_completion_scheduler_t<_CPO> get_completion_scheduler; template @@ -164,7 +144,7 @@ namespace STDEXEC { extern const get_domain_t get_domain; template - concept __is_debug_env = __callable<__queries::__debug_env_t, _Env>; + concept __is_debug_env = __callable<__debug_env_t, _Env>; namespace __debug { struct __completion_signatures { }; @@ -174,15 +154,6 @@ namespace STDEXEC { STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) constexpr auto get_completion_behavior() noexcept; - struct never_stop_token; - class inplace_stop_source; - class inplace_stop_token; - template - class inplace_stop_callback; - - template - using stop_token_of_t = __decay_t<__call_result_t>; - template using __domain_of_t = __decay_t<__call_result_t>; @@ -373,3 +344,54 @@ namespace STDEXEC { using __on::on_t; extern const on_t on; } // namespace STDEXEC + +STDEXEC_P2300_NAMESPACE_BEGIN() +struct forwarding_query_t; +struct get_allocator_t; +struct get_stop_token_t; + +extern const forwarding_query_t forwarding_query; +extern const get_allocator_t get_allocator; +extern const get_stop_token_t get_stop_token; + +template +using stop_token_of_t = STDEXEC::__decay_t>; + +struct never_stop_token; +class inplace_stop_source; +class inplace_stop_token; +template +class inplace_stop_callback; +STDEXEC_P2300_NAMESPACE_END() + +//////////////////////////////////////////////////////////////////////////////////////////////////// +STDEXEC_P2300_NAMESPACE_BEGIN(this_thread) +struct sync_wait_t; +struct sync_wait_with_variant_t; +extern const sync_wait_t sync_wait; +extern const sync_wait_with_variant_t sync_wait_with_variant; +STDEXEC_P2300_NAMESPACE_END(this_thread) + +// NOT TO SPEC: make sync_wait et. al. available in namespace STDEXEC (possibly +// std::execution) as well: +namespace STDEXEC { + STDEXEC_P2300_DEPRECATED_SYMBOL(std::forwarding_query_t) + STDEXEC_P2300_DEPRECATED_SYMBOL(std::get_allocator_t) + STDEXEC_P2300_DEPRECATED_SYMBOL(std::get_stop_token_t) + + STDEXEC_P2300_DEPRECATED_SYMBOL(std::forwarding_query) + STDEXEC_P2300_DEPRECATED_SYMBOL(std::get_stop_token) + STDEXEC_P2300_DEPRECATED_SYMBOL(std::get_allocator) + + STDEXEC_P2300_DEPRECATED_SYMBOL(std::stop_token_of_t) + + STDEXEC_P2300_DEPRECATED_SYMBOL(std::never_stop_token) + STDEXEC_P2300_DEPRECATED_SYMBOL(std::inplace_stop_source) + STDEXEC_P2300_DEPRECATED_SYMBOL(std::inplace_stop_token) + STDEXEC_P2300_DEPRECATED_SYMBOL(std::inplace_stop_callback) + + STDEXEC_P2300_DEPRECATED_SYMBOL(std::this_thread::sync_wait_t) + STDEXEC_P2300_DEPRECATED_SYMBOL(std::this_thread::sync_wait) + STDEXEC_P2300_DEPRECATED_SYMBOL(std::this_thread::sync_wait_with_variant_t) + STDEXEC_P2300_DEPRECATED_SYMBOL(std::this_thread::sync_wait_with_variant) +} // namespace STDEXEC diff --git a/include/stdexec/__detail/__queries.hpp b/include/stdexec/__detail/__queries.hpp index 04ccea6d7..b898f5d02 100644 --- a/include/stdexec/__detail/__queries.hpp +++ b/include/stdexec/__detail/__queries.hpp @@ -26,87 +26,59 @@ namespace STDEXEC { ////////////////////////////////////////////////////////////////////////////////////////////////// // [exec.queries] - namespace __queries { - ////////////////////////////////////////////////////////////////////////////////// - // [exec.get.allocator] - struct get_allocator_t : __query { - using __query::operator(); - - // defined in __read_env.hpp - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - constexpr auto operator()() const noexcept; - - template - STDEXEC_ATTRIBUTE(always_inline, host, device) - static constexpr void __validate() noexcept { - static_assert(__nothrow_callable); - static_assert(__allocator_<__call_result_t>); - } - - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - static consteval auto query(forwarding_query_t) noexcept -> bool { - return true; - } - }; - - // NOT TO SPEC: - struct __is_scheduler_affine_t { - template - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - static consteval auto __ensure_bool_constant() noexcept { - if constexpr (__is_bool_constant<_Result>) { - return static_cast(_Result::value); - } else { - static_assert( - __is_bool_constant<_Result>, - "The __is_scheduler_affine query must be one of the following forms:\n" - " static constexpr bool query(__is_scheduler_affine_t) noexcept;\n" - " bool_constant query(__is_scheduler_affine_t) const noexcept;\n" - " bool_constant query(__is_scheduler_affine_t, const Env&) const noexcept;\n"); - } - } - template - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - consteval auto operator()() const noexcept -> bool { - return __completes_where_it_starts; - } - - template <__queryable_with<__is_scheduler_affine_t> _Attrs, class... _Env> - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - consteval auto operator()() const noexcept -> bool { - if constexpr (__statically_queryable_with<_Attrs, __is_scheduler_affine_t>) { - return _Attrs::query(__is_scheduler_affine_t()); - } else { - return __ensure_bool_constant<__query_result_t<_Attrs, __is_scheduler_affine_t>>(); - } + // NOT TO SPEC: + struct __is_scheduler_affine_t { + template + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + static consteval auto __ensure_bool_constant() noexcept { + if constexpr (__is_bool_constant<_Result>) { + return static_cast(_Result::value); + } else { + static_assert( + __is_bool_constant<_Result>, + "The __is_scheduler_affine query must be one of the following forms:\n" + " static constexpr bool query(__is_scheduler_affine_t) noexcept;\n" + " bool_constant query(__is_scheduler_affine_t) const noexcept;\n" + " bool_constant query(__is_scheduler_affine_t, const Env&) const noexcept;\n"); } + } - template - requires __queryable_with<_Attrs, __is_scheduler_affine_t, const _Env&> - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - consteval auto operator()() const noexcept -> bool { - using __result_t = __query_result_t<_Attrs, __is_scheduler_affine_t, const _Env&>; - return __ensure_bool_constant<__result_t>(); - } + template + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + consteval auto operator()() const noexcept -> bool { + return __completes_where_it_starts; + } - template - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - consteval auto operator()(const _Attrs&, const _Env&...) const noexcept -> bool { - return operator()<_Attrs, _Env...>(); + template <__queryable_with<__is_scheduler_affine_t> _Attrs, class... _Env> + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + consteval auto operator()() const noexcept -> bool { + if constexpr (__statically_queryable_with<_Attrs, __is_scheduler_affine_t>) { + return _Attrs::query(__is_scheduler_affine_t()); + } else { + return __ensure_bool_constant<__query_result_t<_Attrs, __is_scheduler_affine_t>>(); } + } - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - static consteval auto query(forwarding_query_t) noexcept -> bool { - return false; - } - }; - } // namespace __queries + template + requires __queryable_with<_Attrs, __is_scheduler_affine_t, const _Env&> + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + consteval auto operator()() const noexcept -> bool { + using __result_t = __query_result_t<_Attrs, __is_scheduler_affine_t, const _Env&>; + return __ensure_bool_constant<__result_t>(); + } - using __queries::get_allocator_t; - using __queries::__is_scheduler_affine_t; + template + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + consteval auto operator()(const _Attrs&, const _Env&...) const noexcept -> bool { + return operator()<_Attrs, _Env...>(); + } - inline constexpr get_allocator_t get_allocator{}; + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + static consteval auto query(forwarding_query_t) noexcept -> bool { + return false; + } + }; template concept __is_scheduler_affine = requires { @@ -142,3 +114,29 @@ namespace STDEXEC { template STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE __sync_attrs(const _Sender&) -> __sync_attrs<_Sender>; } // namespace STDEXEC + +STDEXEC_P2300_NAMESPACE_BEGIN() +////////////////////////////////////////////////////////////////////////////////// +// [exec.get.allocator] +struct get_allocator_t : STDEXEC::__query { + using STDEXEC::__query::operator(); + + // defined in __read_env.hpp + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + constexpr auto operator()() const noexcept; + + template + STDEXEC_ATTRIBUTE(always_inline, host, device) + static constexpr void __validate() noexcept { + static_assert(STDEXEC::__nothrow_callable); + static_assert(STDEXEC::__allocator_>); + } + + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + static consteval auto query(forwarding_query_t) noexcept -> bool { + return true; + } +}; + +inline constexpr get_allocator_t get_allocator{}; +STDEXEC_P2300_NAMESPACE_END() diff --git a/include/stdexec/__detail/__query.hpp b/include/stdexec/__detail/__query.hpp index 2802c08c1..670805e98 100644 --- a/include/stdexec/__detail/__query.hpp +++ b/include/stdexec/__detail/__query.hpp @@ -28,11 +28,11 @@ namespace STDEXEC { // [exec.queries.queryable] template - concept queryable = __std::destructible; + concept __queryable = __std::destructible; template concept __member_queryable_with = - queryable<_Env> + __queryable<_Env> && requires(const _Env& __env, const _Query& __query, __declfn_t<_Args&&>... __args) { { __env.query(__query, __args()...) }; }; @@ -120,55 +120,12 @@ namespace STDEXEC { ////////////////////////////////////////////////////////////////////////////////////////////////// // [exec.queries] - namespace __queries { - template - concept __is_bool_constant = requires { typename __mbool<_Tp::value>; }; - - struct forwarding_query_t { - template - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - consteval auto operator()(_Query) const noexcept -> bool { - if constexpr (__queryable_with<_Query, forwarding_query_t>) { - return __query()(_Query()); - } else { - return __std::derived_from<_Query, forwarding_query_t>; - } - } - }; - - } // namespace __queries - - using __queries::forwarding_query_t; - inline constexpr forwarding_query_t forwarding_query{}; + template + concept __is_bool_constant = requires { typename __mbool<_Tp::value>; }; template concept __forwarding_query = forwarding_query(_Tag{}); - struct query_or_t { - template - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - constexpr auto operator()(_Query, _Queryable&&, _Default&& __default, _Args&&...) const - noexcept(__nothrow_move_constructible<_Default>) -> _Default { - return static_cast<_Default&&>(__default); - } - - template - requires __callable<_Query, _Queryable, _Args...> - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - constexpr auto - operator()(_Query __query, _Queryable&& __queryable, _Default&&, _Args&&... __args) const - noexcept(__nothrow_callable<_Query, _Queryable, _Args...>) - -> __call_result_t<_Query, _Queryable, _Args...> { - return static_cast<_Query&&>( - __query)(static_cast<_Queryable&&>(__queryable), static_cast<_Args&&>(__args)...); - } - }; - - inline constexpr query_or_t query_or{}; // NOT TO SPEC - - template - using __query_result_or_t = __call_result_t; - ////////////////////////////////////////////////////////////////////////////////////////// // __is_completion_query template @@ -180,3 +137,19 @@ namespace STDEXEC { template inline constexpr bool __is_completion_query> = true; } // namespace STDEXEC + +STDEXEC_P2300_NAMESPACE_BEGIN() +struct forwarding_query_t { + template + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + consteval auto operator()(_Query) const noexcept -> bool { + if constexpr (STDEXEC::__queryable_with<_Query, forwarding_query_t>) { + return STDEXEC::__query()(_Query()); + } else { + return STDEXEC::__std::derived_from<_Query, forwarding_query_t>; + } + } +}; + +inline constexpr forwarding_query_t forwarding_query{}; +STDEXEC_P2300_NAMESPACE_END() diff --git a/include/stdexec/__detail/__read_env.hpp b/include/stdexec/__detail/__read_env.hpp index a43c33e5d..da7a9f7d6 100644 --- a/include/stdexec/__detail/__read_env.hpp +++ b/include/stdexec/__detail/__read_env.hpp @@ -144,25 +144,25 @@ namespace STDEXEC { template <> struct __sexpr_impl<__read::read_env_t> : __read::__read_env_impl { }; - namespace __queries { - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - constexpr auto get_scheduler_t::operator()() const noexcept { - return read_env(get_scheduler); - } - - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - constexpr auto get_delegation_scheduler_t::operator()() const noexcept { - return read_env(get_delegation_scheduler); - } - - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - constexpr auto get_allocator_t::operator()() const noexcept { - return read_env(get_allocator); - } - - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - constexpr auto get_stop_token_t::operator()() const noexcept { - return read_env(get_stop_token); - } - } // namespace __queries + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + constexpr auto get_scheduler_t::operator()() const noexcept { + return read_env(get_scheduler); + } + + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) + constexpr auto get_delegation_scheduler_t::operator()() const noexcept { + return read_env(get_delegation_scheduler); + } } // namespace STDEXEC + +STDEXEC_P2300_NAMESPACE_BEGIN() +STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) +constexpr auto get_allocator_t::operator()() const noexcept { + return STDEXEC::read_env(get_allocator); +} + +STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) +constexpr auto get_stop_token_t::operator()() const noexcept { + return STDEXEC::read_env(get_stop_token); +} +STDEXEC_P2300_NAMESPACE_END() diff --git a/include/stdexec/__detail/__receivers.hpp b/include/stdexec/__detail/__receivers.hpp index 2b4e47eb4..96947d203 100644 --- a/include/stdexec/__detail/__receivers.hpp +++ b/include/stdexec/__detail/__receivers.hpp @@ -183,7 +183,7 @@ namespace STDEXEC { template concept receiver = enable_receiver<__decay_t<_Receiver>> - && environment_provider<__cref_t<_Receiver>> + && __environment_provider<__cref_t<_Receiver>> && __nothrow_move_constructible<__decay_t<_Receiver>> && __std::constructible_from<__decay_t<_Receiver>, _Receiver>; diff --git a/include/stdexec/__detail/__run_loop.hpp b/include/stdexec/__detail/__run_loop.hpp index bf630e507..ddb5f4444 100644 --- a/include/stdexec/__detail/__run_loop.hpp +++ b/include/stdexec/__detail/__run_loop.hpp @@ -191,7 +191,7 @@ namespace STDEXEC { } STDEXEC_ATTRIBUTE(nodiscard, host, device) - constexpr auto query(execute_may_block_caller_t) const noexcept { + constexpr auto query(__execute_may_block_caller_t) const noexcept { return false; } diff --git a/include/stdexec/__detail/__schedulers.hpp b/include/stdexec/__detail/__schedulers.hpp index 72d4d52e4..de70058df 100644 --- a/include/stdexec/__detail/__schedulers.hpp +++ b/include/stdexec/__detail/__schedulers.hpp @@ -85,7 +85,6 @@ namespace STDEXEC { { get_scheduler(__sp) } -> scheduler; }; - namespace __queries { struct get_scheduler_t : __query { using __query::operator(); @@ -279,16 +278,18 @@ namespace STDEXEC { } }; - struct execute_may_block_caller_t : __query { + struct __execute_may_block_caller_t : __query<__execute_may_block_caller_t, true> { template STDEXEC_ATTRIBUTE(always_inline, host, device) static constexpr void __validate() noexcept { static_assert( - __std::same_as>); - static_assert(__nothrow_callable); + __std::same_as>); + static_assert(__nothrow_callable<__execute_may_block_caller_t, const _Attrs&>); } }; + using execute_may_block_caller_t [[deprecated]] = __execute_may_block_caller_t; + struct get_forward_progress_guarantee_t : __query< get_forward_progress_guarantee_t, @@ -303,15 +304,9 @@ namespace STDEXEC { static_assert(__nothrow_callable); } }; - } // namespace __queries - - using __queries::execute_may_block_caller_t; - using __queries::get_forward_progress_guarantee_t; - using __queries::get_scheduler_t; - using __queries::get_delegation_scheduler_t; - using __queries::get_completion_scheduler_t; - inline constexpr execute_may_block_caller_t execute_may_block_caller{}; + [[deprecated]] + inline constexpr __execute_may_block_caller_t execute_may_block_caller{}; inline constexpr get_forward_progress_guarantee_t get_forward_progress_guarantee{}; inline constexpr get_scheduler_t get_scheduler{}; inline constexpr get_delegation_scheduler_t get_delegation_scheduler{}; @@ -388,7 +383,7 @@ namespace STDEXEC { && (__callable || ...)) { return ( __sched_env{get_completion_scheduler( - get_scheduler(__env), __queries::__hide_scheduler{__env})}, + get_scheduler(__env), __hide_scheduler{__env})}, ...); } else { return __sched_env{__sch}; diff --git a/include/stdexec/__detail/__sender_concepts.hpp b/include/stdexec/__detail/__sender_concepts.hpp index e085a8ecc..fc527b9b0 100644 --- a/include/stdexec/__detail/__sender_concepts.hpp +++ b/include/stdexec/__detail/__sender_concepts.hpp @@ -48,7 +48,7 @@ namespace STDEXEC { // [exec.snd.concepts] template concept sender = enable_sender<__decay_t<_Sender>> // - && environment_provider<__cref_t<_Sender>> // + && __environment_provider<__cref_t<_Sender>> // && __std::move_constructible<__decay_t<_Sender>> && __std::constructible_from<__decay_t<_Sender>, _Sender>; diff --git a/include/stdexec/__detail/__stop_token.hpp b/include/stdexec/__detail/__stop_token.hpp index 2271df24f..f6986f7e7 100644 --- a/include/stdexec/__detail/__stop_token.hpp +++ b/include/stdexec/__detail/__stop_token.hpp @@ -20,88 +20,86 @@ #include "__concepts.hpp" -STDEXEC_NAMESPACE_STD_BEGIN -class stop_token; +#if defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 2019'11L +# include +#endif -template -class stop_callback; -STDEXEC_NAMESPACE_STD_END +STDEXEC_P2300_NAMESPACE_BEGIN() -namespace STDEXEC { - namespace __stok { - template