From b3a29452f1c910d0dd8a0d96445cf59d1e62e5b8 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Sun, 23 Mar 2025 19:18:44 -0700 Subject: [PATCH] try to bring down the length of symbols a bit --- .../__system_context_default_impl.hpp | 7 +- .../__system_context_replaceability_api.hpp | 2 +- include/exec/libdispatch_queue.hpp | 2 +- include/exec/start_now.hpp | 12 +- include/exec/system_context.hpp | 2 +- include/stdexec/__detail/__basic_sender.hpp | 454 +++++++++--------- include/stdexec/__detail/__env.hpp | 22 + include/stdexec/__detail/__let.hpp | 65 +-- include/stdexec/__detail/__meta.hpp | 17 +- include/stdexec/__detail/__on.hpp | 3 +- include/stdexec/__detail/__schedule_from.hpp | 48 +- include/stdexec/__detail/__schedulers.hpp | 14 - include/stdexec/__detail/__starts_on.hpp | 3 +- 13 files changed, 336 insertions(+), 315 deletions(-) diff --git a/include/exec/__detail/__system_context_default_impl.hpp b/include/exec/__detail/__system_context_default_impl.hpp index 3ba6d6897..fddf1ad44 100644 --- a/include/exec/__detail/__system_context_default_impl.hpp +++ b/include/exec/__detail/__system_context_default_impl.hpp @@ -16,10 +16,11 @@ #pragma once #include "__system_context_replaceability_api.hpp" -#include "stdexec/execution.hpp" -#include "exec/static_thread_pool.hpp" + +#include "../../stdexec/execution.hpp" +#include "../static_thread_pool.hpp" #if STDEXEC_ENABLE_LIBDISPATCH -# include "exec/libdispatch_queue.hpp" +# include "../libdispatch_queue.hpp" // IWYU pragma: keep #endif #include diff --git a/include/exec/__detail/__system_context_replaceability_api.hpp b/include/exec/__detail/__system_context_replaceability_api.hpp index 083ae4496..4eb9ca299 100644 --- a/include/exec/__detail/__system_context_replaceability_api.hpp +++ b/include/exec/__detail/__system_context_replaceability_api.hpp @@ -17,7 +17,7 @@ #ifndef STDEXEC_SYSTEM_CONTEXT_REPLACEABILITY_API_H #define STDEXEC_SYSTEM_CONTEXT_REPLACEABILITY_API_H -#include "stdexec/__detail/__execution_fwd.hpp" +#include "../../stdexec/__detail/__execution_fwd.hpp" #include #include diff --git a/include/exec/libdispatch_queue.hpp b/include/exec/libdispatch_queue.hpp index 1f1b4d659..14ddeb052 100644 --- a/include/exec/libdispatch_queue.hpp +++ b/include/exec/libdispatch_queue.hpp @@ -27,7 +27,7 @@ # define __has_extension(x) false # endif -# include "stdexec/execution.hpp" +# include "../stdexec/execution.hpp" # include namespace exec { diff --git a/include/exec/start_now.hpp b/include/exec/start_now.hpp index 659fbda35..54695410a 100644 --- a/include/exec/start_now.hpp +++ b/include/exec/start_now.hpp @@ -15,13 +15,13 @@ */ #pragma once -#include "stdexec/__detail/__execution_fwd.hpp" +#include "../stdexec/__detail/__execution_fwd.hpp" -#include "stdexec/__detail/__concepts.hpp" -#include "stdexec/__detail/__env.hpp" -#include "stdexec/__detail/__receivers.hpp" -#include "stdexec/__detail/__senders.hpp" -#include "stdexec/__detail/__meta.hpp" +#include "../stdexec/__detail/__concepts.hpp" +#include "../stdexec/__detail/__env.hpp" +#include "../stdexec/__detail/__receivers.hpp" +#include "../stdexec/__detail/__senders.hpp" +#include "../stdexec/__detail/__meta.hpp" #include "async_scope.hpp" diff --git a/include/exec/system_context.hpp b/include/exec/system_context.hpp index 4ed055bf5..c7a8ed1fd 100644 --- a/include/exec/system_context.hpp +++ b/include/exec/system_context.hpp @@ -17,7 +17,7 @@ #include -#include "stdexec/execution.hpp" +#include "../stdexec/execution.hpp" #include "__detail/__system_context_replaceability_api.hpp" #ifndef STDEXEC_SYSTEM_CONTEXT_SCHEDULE_OP_SIZE diff --git a/include/stdexec/__detail/__basic_sender.hpp b/include/stdexec/__detail/__basic_sender.hpp index 49116fdfb..2a4d0ea52 100644 --- a/include/stdexec/__detail/__basic_sender.hpp +++ b/include/stdexec/__detail/__basic_sender.hpp @@ -39,20 +39,18 @@ namespace stdexec { using __impl_of = decltype((__declval<_Sender>().__impl_)); } // namespace __detail - namespace { - template < - class _Descriptor, - auto _DescriptorFn = - [] { - return _Descriptor(); - }> - inline constexpr auto __descriptor_fn_v = _DescriptorFn; + template < + class _Descriptor, + auto _DescriptorFn = + [] { + return _Descriptor(); + }> + inline constexpr auto __descriptor_fn_v = _DescriptorFn; - template - inline constexpr auto __descriptor_fn() { - return __descriptor_fn_v<__detail::__desc<_Tag, _Data, _Child...>>; - } - } // namespace + template + inline constexpr auto __descriptor_fn() { + return __descriptor_fn_v<__detail::__desc<_Tag, _Data, _Child...>>; + } #if STDEXEC_EDG() # define STDEXEC_SEXPR_DESCRIPTOR(_Tag, _Data, _Child) \ @@ -65,10 +63,13 @@ namespace stdexec { template struct __sexpr_impl; - namespace __detail { - template - struct __op_state; + template + struct __op_state; + template + struct __rcvr; + + namespace __detail { template struct __connect_fn; @@ -88,97 +89,62 @@ namespace stdexec { __callable<__impl_of<_Sexpr>, __copy_cvref_fn<_Sexpr>, __connect_fn<_Sexpr, _Receiver>> && __mvalid<__state_type_t, tag_of_t<_Sexpr>, _Sexpr, _Receiver>; - inline constexpr auto __get_attrs = // - [](__ignore, const auto&... __child) noexcept -> decltype(auto) { - if constexpr (sizeof...(__child) == 1) { - return __env::__fwd_fn()(stdexec::get_env(__child...)); - } else { - return empty_env(); - } - }; - - inline constexpr auto __get_env = // - [](__ignore, __ignore, const _Receiver& __rcvr) noexcept - -> env_of_t { - return stdexec::get_env(__rcvr); - }; - - inline constexpr auto __get_state = // - [](_Sender&& __sndr, __ignore) noexcept -> decltype(auto) { - return __sndr.apply(static_cast<_Sender&&>(__sndr), __get_data()); - }; - - inline constexpr auto __connect = // - [](_Sender&& __sndr, _Receiver __rcvr) // - noexcept(__nothrow_constructible_from<__op_state<_Sender, _Receiver>, _Sender, _Receiver>) - -> __op_state<_Sender, _Receiver> - requires __connectable<_Sender, _Receiver> - { - return __op_state<_Sender, _Receiver>{ - static_cast<_Sender&&>(__sndr), static_cast<_Receiver&&>(__rcvr)}; - }; - - inline constexpr auto __start = // - []( - __ignore, - __ignore, - _ChildOps&... __ops) noexcept { - (_StartTag()(__ops), ...); + struct __defaults { + static constexpr auto get_attrs = // + [](__ignore, const auto&... __child) noexcept -> decltype(auto) { + if constexpr (sizeof...(__child) == 1) { + return __env::__fwd_fn()(stdexec::get_env(__child...)); + } else { + return empty_env(); + } }; - inline constexpr auto __complete = // - []( - _Index, - __ignore, - _Receiver& __rcvr, - _SetTag, - _Args&&... __args) noexcept { - static_assert(__v<_Index> == 0, "I don't know how to complete this operation."); - _SetTag()(std::move(__rcvr), static_cast<_Args&&>(__args)...); + static constexpr auto get_env = // + [](__ignore, __ignore, const _Receiver& __rcvr) noexcept + -> env_of_t { + return stdexec::get_env(__rcvr); }; - inline constexpr auto __sigs = // - [](_Sender&& __sndr, __ignore = {}) noexcept { - static_assert( - __mnever>, - "No customization of get_completion_signatures for this sender tag type."); + static constexpr auto get_state = // + [](_Sender&& __sndr, __ignore) noexcept -> decltype(auto) { + return __sndr.apply(static_cast<_Sender&&>(__sndr), __get_data()); }; - template - struct __receiver { - struct __t { - using receiver_concept = receiver_t; - using _Receiver = stdexec::__t<_ReceiverId>; - using __sexpr = _Sexpr; - using __index = _Idx; - using __id = __receiver; - using __parent_op_t = __op_state<_Sexpr, _Receiver>; - using __tag_t = tag_of_t<_Sexpr>; - - // A pointer to the parent operation state, which contains the one created with - // this receiver. - __parent_op_t* __op_; - - template - STDEXEC_ATTRIBUTE((always_inline)) void set_value(_Args&&... __args) noexcept { - __op_->__complete(_Idx(), stdexec::set_value, static_cast<_Args&&>(__args)...); - } - - template - STDEXEC_ATTRIBUTE((always_inline)) void set_error(_Error&& __err) noexcept { - __op_->__complete(_Idx(), stdexec::set_error, static_cast<_Error&&>(__err)); - } - - STDEXEC_ATTRIBUTE((always_inline)) void set_stopped() noexcept { - __op_->__complete(_Idx(), stdexec::set_stopped); - } - - template <__same_as<__t> _Self = __t> - STDEXEC_ATTRIBUTE((always_inline)) auto - get_env() const noexcept -> __env_type_t<_Self, __tag_t, _Idx, _Sexpr, _Receiver> { - return __op_->__get_env(_Idx()); - } + static constexpr auto connect = // + [](_Sender&& __sndr, _Receiver __rcvr) // + noexcept(__nothrow_constructible_from<__op_state<_Sender, _Receiver>, _Sender, _Receiver>) + -> __op_state<_Sender, _Receiver> + requires __connectable<_Sender, _Receiver> + { + return __op_state<_Sender, _Receiver>{ + static_cast<_Sender&&>(__sndr), static_cast<_Receiver&&>(__rcvr)}; }; + + static constexpr auto start = // + []( + __ignore, + __ignore, + _ChildOps&... __ops) noexcept { + (_StartTag()(__ops), ...); + }; + + static constexpr auto complete = // + []( + _Index, + __ignore, + _Receiver& __rcvr, + _SetTag, + _Args&&... __args) noexcept { + static_assert(__v<_Index> == 0, "I don't know how to complete this operation."); + _SetTag()(std::move(__rcvr), static_cast<_Args&&>(__args)...); + }; + + static constexpr auto get_completion_signatures = // + [](_Sender&& __sndr, __ignore = {}) noexcept { + static_assert( + __mnever>, + "No customization of get_completion_signatures for this sender tag type."); + }; }; template @@ -311,7 +277,7 @@ namespace stdexec { template struct __connect_fn { template - using __receiver_t = __t<__receiver<__id<_Receiver>, _Sexpr, __msize_t<_Idx>>>; + using __receiver_t = __t<__rcvr<__id<_Receiver>, _Sexpr, _Idx>>; __op_state<_Sexpr, _Receiver>* __op_; @@ -340,56 +306,6 @@ namespace stdexec { STDEXEC_PRAGMA_POP() - template - struct __op_state : __op_base<_Sexpr, _Receiver> { - using __desc_t = typename __decay_t<_Sexpr>::__desc_t; - using __tag_t = typename __desc_t::__tag; - using __data_t = typename __desc_t::__data; - using __state_t = typename __op_state::__state_t; - using __inner_ops_t = __result_of<__sexpr_apply, _Sexpr, __connect_fn<_Sexpr, _Receiver>>; - - __inner_ops_t __inner_ops_; - - __op_state(_Sexpr&& __sexpr, _Receiver __rcvr) // - noexcept( - __nothrow_constructible_from<__op_base<_Sexpr, _Receiver>, _Sexpr, _Receiver> - && __noexcept_of<__sexpr_apply, _Sexpr, __connect_fn<_Sexpr, _Receiver>>) - : __op_state::__op_base{static_cast<_Sexpr&&>(__sexpr), static_cast<_Receiver&&>(__rcvr)} - , __inner_ops_( - __sexpr_apply(static_cast<_Sexpr&&>(__sexpr), __connect_fn<_Sexpr, _Receiver>{this})) { - } - - STDEXEC_ATTRIBUTE((always_inline)) void start() & noexcept { - using __tag_t = typename __op_state::__tag_t; - auto&& __rcvr = this->__rcvr(); - __inner_ops_.apply( - [&](auto&... __ops) noexcept { - __sexpr_impl<__tag_t>::start(this->__state(), __rcvr, __ops...); - }, - __inner_ops_); - } - - template - STDEXEC_ATTRIBUTE((always_inline)) void __complete(_Index, _Tag2, _Args&&... __args) noexcept { - using __tag_t = typename __op_state::__tag_t; - auto&& __rcvr = this->__rcvr(); - using _CompleteFn = __mtypeof<__sexpr_impl<__tag_t>::complete>; - if constexpr (__callable<_CompleteFn, _Index, __op_state&, _Tag2, _Args...>) { - __sexpr_impl<__tag_t>::complete(_Index(), *this, _Tag2(), static_cast<_Args&&>(__args)...); - } else { - __sexpr_impl<__tag_t>::complete( - _Index(), this->__state(), __rcvr, _Tag2(), static_cast<_Args&&>(__args)...); - } - } - - template - STDEXEC_ATTRIBUTE((always_inline)) auto __get_env(_Index) const noexcept - -> __env_type_t<_Index, __tag_t, _Index, _Sexpr, _Receiver> { - const auto& __rcvr = this->__rcvr(); - return __sexpr_impl<__tag_t>::get_env(_Index(), this->__state(), __rcvr); - } - }; - inline constexpr auto __drop_front = // [](_Fn __fn) noexcept { return [__fn = std::move(__fn)](auto&&, _Rest&&... __rest) // @@ -426,18 +342,100 @@ namespace stdexec { } // namespace __detail - struct __sexpr_defaults { - static constexpr auto get_attrs = __detail::__get_attrs; - static constexpr auto get_env = __detail::__get_env; - static constexpr auto get_state = __detail::__get_state; - static constexpr auto connect = __detail::__connect; - static constexpr auto start = __detail::__start; - static constexpr auto complete = __detail::__complete; - static constexpr auto get_completion_signatures = __detail::__sigs; + using __sexpr_defaults = __detail::__defaults; + + template + struct __rcvr { + using _Receiver = stdexec::__t<_ReceiverId>; + + struct __t { + using receiver_concept = receiver_t; + using __id = __rcvr; + + using __index = __msize_t<_Idx>; + using __parent_op_t = __op_state<_Sexpr, _Receiver>; + using __tag_t = tag_of_t<_Sexpr>; + + // A pointer to the parent operation state, which contains the one created with + // this receiver. + __parent_op_t* __op_; + + template + STDEXEC_ATTRIBUTE((always_inline)) void set_value(_Args&&... __args) noexcept { + __op_->__complete(__index(), stdexec::set_value, static_cast<_Args&&>(__args)...); + } + + template + STDEXEC_ATTRIBUTE((always_inline)) void set_error(_Error&& __err) noexcept { + __op_->__complete(__index(), stdexec::set_error, static_cast<_Error&&>(__err)); + } + + STDEXEC_ATTRIBUTE((always_inline)) void set_stopped() noexcept { + __op_->__complete(__index(), stdexec::set_stopped); + } + + template <__same_as<__t> _Self = __t> + STDEXEC_ATTRIBUTE((always_inline)) auto get_env() const noexcept + -> __detail::__env_type_t<_Self, __tag_t, __index, _Sexpr, _Receiver> { + return __op_->__get_env(__index()); + } + }; + }; + + template + struct __op_state : __detail::__op_base<_Sexpr, _Receiver> { + using __desc_t = typename __decay_t<_Sexpr>::__desc_t; + using __tag_t = typename __desc_t::__tag; + using __data_t = typename __desc_t::__data; + using __state_t = typename __op_state::__state_t; + using __inner_ops_t = + __result_of<__sexpr_apply, _Sexpr, __detail::__connect_fn<_Sexpr, _Receiver>>; + + __inner_ops_t __inner_ops_; + + __op_state(_Sexpr&& __sexpr, _Receiver __rcvr) // + noexcept( + __nothrow_constructible_from<__detail::__op_base<_Sexpr, _Receiver>, _Sexpr, _Receiver> + && __noexcept_of<__sexpr_apply, _Sexpr, __detail::__connect_fn<_Sexpr, _Receiver>>) + : __op_state::__op_base{static_cast<_Sexpr&&>(__sexpr), static_cast<_Receiver&&>(__rcvr)} + , __inner_ops_(__sexpr_apply( + static_cast<_Sexpr&&>(__sexpr), + __detail::__connect_fn<_Sexpr, _Receiver>{this})) { + } + + STDEXEC_ATTRIBUTE((always_inline)) void start() & noexcept { + using __tag_t = typename __op_state::__tag_t; + auto&& __rcvr = this->__rcvr(); + __inner_ops_.apply( + [&](auto&... __ops) noexcept { + __sexpr_impl<__tag_t>::start(this->__state(), __rcvr, __ops...); + }, + __inner_ops_); + } + + template + STDEXEC_ATTRIBUTE((always_inline)) void __complete(_Index, _Tag2, _Args&&... __args) noexcept { + using __tag_t = typename __op_state::__tag_t; + auto&& __rcvr = this->__rcvr(); + using _CompleteFn = __mtypeof<__sexpr_impl<__tag_t>::complete>; + if constexpr (__callable<_CompleteFn, _Index, __op_state&, _Tag2, _Args...>) { + __sexpr_impl<__tag_t>::complete(_Index(), *this, _Tag2(), static_cast<_Args&&>(__args)...); + } else { + __sexpr_impl<__tag_t>::complete( + _Index(), this->__state(), __rcvr, _Tag2(), static_cast<_Args&&>(__args)...); + } + } + + template + STDEXEC_ATTRIBUTE((always_inline)) auto __get_env(_Index) const noexcept + -> __detail::__env_type_t<_Index, __tag_t, _Index, _Sexpr, _Receiver> { + const auto& __rcvr = this->__rcvr(); + return __sexpr_impl<__tag_t>::get_env(_Index(), this->__state(), __rcvr); + } }; template - struct __sexpr_impl : __sexpr_defaults { + struct __sexpr_impl : __detail::__defaults { using not_specialized = void; }; @@ -456,82 +454,86 @@ namespace stdexec { using __t = __basic_sender; }; - //! A struct template to aid in creating senders. - //! This struct closely resembles P2300's [_`basic-sender`_](https://eel.is/c++draft/exec#snd.expos-24), - //! but is not an exact implementation. - //! Note: The struct named `__basic_sender` is just a dummy type and is also not _`basic-sender`_. - template - struct __sexpr { - using sender_concept = sender_t; - - // See MAINTAINERS.md#class-template-parameters for `__id` and `__t`. - using __id = __sexpr; - using __t = __sexpr; - using __desc_t = decltype(_DescriptorFn()); - using __tag_t = typename __desc_t::__tag; - using __captures_t = __minvoke<__desc_t, __q<__detail::__captures_t>>; + namespace { + //! A struct template to aid in creating senders. + //! This struct closely resembles P2300's [_`basic-sender`_](https://eel.is/c++draft/exec#snd.expos-24), + //! but is not an exact implementation. + //! Note: The struct named `__basic_sender` is just a dummy type and is also not _`basic-sender`_. + template + struct __sexpr { + using sender_concept = sender_t; + + // See MAINTAINERS.md#class-template-parameters for `__id` and `__t`. + using __id = __sexpr; + using __t = __sexpr; + using __desc_t = decltype(_DescriptorFn()); + using __tag_t = typename __desc_t::__tag; + using __captures_t = __minvoke<__desc_t, __q<__detail::__captures_t>>; - mutable __captures_t __impl_; + mutable __captures_t __impl_; - template - STDEXEC_ATTRIBUTE((host, device, always_inline)) explicit __sexpr(_Tag, _Data&& __data, _Child&&... __child) - : __impl_( - __detail::__captures( - _Tag(), - static_cast<_Data&&>(__data), - static_cast<_Child&&>(__child)...)) { - } + template + STDEXEC_ATTRIBUTE((host, device, always_inline)) explicit __sexpr(_Tag, _Data&& __data, _Child&&... __child) + : __impl_( + __detail::__captures( + _Tag(), + static_cast<_Data&&>(__data), + static_cast<_Child&&>(__child)...)) { + } - template - using __impl = __sexpr_impl<__meval<__msecond, _Self, __tag_t>>; + template + using __impl = __sexpr_impl<__meval<__msecond, _Self, __tag_t>>; - template - STDEXEC_ATTRIBUTE((always_inline)) auto get_env() const noexcept - -> __result_of<__sexpr_apply, const _Self&, __get_attrs_fn<__tag_t>> { - return __sexpr_apply(*this, __detail::__drop_front(__impl<_Self>::get_attrs)); - } + template + STDEXEC_ATTRIBUTE((always_inline)) auto get_env() const noexcept + -> __result_of<__sexpr_apply, const _Self&, __get_attrs_fn<__tag_t>> { + return __sexpr_apply(*this, __detail::__drop_front(__impl<_Self>::get_attrs)); + } - template <__decays_to<__sexpr> _Self, class... _Env> - STDEXEC_ATTRIBUTE((always_inline)) static auto get_completion_signatures(_Self&&, _Env&&...) noexcept // - -> __msecond< - __if_c<__decays_to<_Self, __sexpr>>, - __result_of<__impl<_Self>::get_completion_signatures, _Self, _Env...>> { - return {}; - } + template <__decays_to<__sexpr> _Self, class... _Env> + STDEXEC_ATTRIBUTE((always_inline)) static auto get_completion_signatures(_Self&&, _Env&&...) noexcept // + -> __msecond< + __if_c<__decays_to<_Self, __sexpr>>, + __result_of<__impl<_Self>::get_completion_signatures, _Self, _Env...>> { + return {}; + } - // BUGBUG fix receiver constraint here: - template <__decays_to<__sexpr> _Self, /*receiver*/ class _Receiver> - STDEXEC_ATTRIBUTE((always_inline)) static auto connect(_Self&& __self, _Receiver&& __rcvr) // - noexcept(__noexcept_of<__impl<_Self>::connect, _Self, _Receiver>) // - -> __msecond< - __if_c<__decays_to<_Self, __sexpr>>, - __result_of<__impl<_Self>::connect, _Self, _Receiver>> { - return __impl<_Self>::connect(static_cast<_Self&&>(__self), static_cast<_Receiver&&>(__rcvr)); - } + // BUGBUG fix receiver constraint here: + template <__decays_to<__sexpr> _Self, /*receiver*/ class _Receiver> + STDEXEC_ATTRIBUTE((always_inline)) static auto connect(_Self&& __self, _Receiver&& __rcvr) // + noexcept(__noexcept_of<__impl<_Self>::connect, _Self, _Receiver>) // + -> __msecond< + __if_c<__decays_to<_Self, __sexpr>>, + __result_of<__impl<_Self>::connect, _Self, _Receiver>> { + return __impl<_Self>::connect( + static_cast<_Self&&>(__self), static_cast<_Receiver&&>(__rcvr)); + } - template - STDEXEC_ATTRIBUTE((always_inline)) static auto apply(_Sender&& __sndr, _ApplyFn&& __fun) // - noexcept( - __nothrow_callable<__detail::__impl_of<_Sender>, __copy_cvref_fn<_Sender>, _ApplyFn>) // - -> __call_result_t<__detail::__impl_of<_Sender>, __copy_cvref_fn<_Sender>, _ApplyFn> { // - return static_cast<_Sender&&>(__sndr).__impl_( - __copy_cvref_fn<_Sender>(), static_cast<_ApplyFn&&>(__fun)); // - } + template + STDEXEC_ATTRIBUTE((always_inline)) static auto apply(_Sender&& __sndr, _ApplyFn&& __fun) // + noexcept( + __nothrow_callable<__detail::__impl_of<_Sender>, __copy_cvref_fn<_Sender>, _ApplyFn>) // + -> __call_result_t<__detail::__impl_of<_Sender>, __copy_cvref_fn<_Sender>, _ApplyFn> { // + return static_cast<_Sender&&>(__sndr).__impl_( + __copy_cvref_fn<_Sender>(), static_cast<_ApplyFn&&>(__fun)); // + } - template _Self> - STDEXEC_ATTRIBUTE((always_inline)) friend auto get(_Self&& __self) noexcept -> decltype(auto) - requires __detail::__in_range<_Idx, __desc_t> - { - if constexpr (_Idx == 0) { - return __tag_t(); - } else { - return __self.__impl_(__copy_cvref_fn<_Self>(), __nth_pack_element<_Idx>); + template _Self> + STDEXEC_ATTRIBUTE((always_inline)) friend auto get(_Self&& __self) noexcept -> decltype(auto) + requires __detail::__in_range<_Idx, __desc_t> + { + if constexpr (_Idx == 0) { + return __tag_t(); + } else { + return __self.__impl_(__copy_cvref_fn<_Self>(), __nth_pack_element<_Idx>); + } } - } - }; + }; - template - STDEXEC_ATTRIBUTE((host, device)) __sexpr(_Tag, _Data, _Child...) -> __sexpr; + template + STDEXEC_ATTRIBUTE((host, device)) __sexpr(_Tag, _Data, _Child...) + -> __sexpr; + } // namespace template using __sexpr_t = __sexpr; diff --git a/include/stdexec/__detail/__env.hpp b/include/stdexec/__detail/__env.hpp index e66312ea3..53bba902b 100644 --- a/include/stdexec/__detail/__env.hpp +++ b/include/stdexec/__detail/__env.hpp @@ -26,6 +26,7 @@ #include #include // IWYU pragma: keep for unwrap_reference_t +#include STDEXEC_PRAGMA_PUSH() STDEXEC_PRAGMA_IGNORE_EDG(probable_guiding_friend) @@ -685,6 +686,27 @@ namespace stdexec { template __sched_attrs(_Scheduler) -> __sched_attrs>; + template + struct __sched_env { + using __t = __sched_env; + using __id = __sched_env; + + using __scheduler_t = __decay_t<_Scheduler>; + _Scheduler __sched_; + + auto query(get_scheduler_t) const noexcept -> __scheduler_t { + return __sched_; + } + + template + auto query(get_domain_t) const noexcept -> __domain_of_t<_Sched> { + return get_domain(__sched_); + } + }; + + template + __sched_env(_Scheduler) -> __sched_env>; + using __env::__as_root_env_t; using __env::__as_root_env; diff --git a/include/stdexec/__detail/__let.hpp b/include/stdexec/__detail/__let.hpp index c475ae816..ad8c4e70f 100644 --- a/include/stdexec/__detail/__let.hpp +++ b/include/stdexec/__detail/__let.hpp @@ -93,34 +93,39 @@ namespace stdexec { template using __on_not_callable = __callable_error<__in_which_let_msg<_Set>>; - template - struct __receiver_with_sched { - using receiver_concept = receiver_t; - _Receiver __rcvr_; - _Scheduler __sched_; - - template - void set_value(_As&&... __as) noexcept { - stdexec::set_value(static_cast<_Receiver&&>(__rcvr_), static_cast<_As&&>(__as)...); - } + template + struct __rcvr_sch { + using _Receiver = stdexec::__t<_ReceiverId>; + using _Scheduler = stdexec::__t<_SchedulerId>; + + struct __t { + using receiver_concept = receiver_t; + using __id = __rcvr_sch; + _Receiver __rcvr_; + _Scheduler __sched_; + + template + void set_value(_As&&... __as) noexcept { + stdexec::set_value(static_cast<_Receiver&&>(__rcvr_), static_cast<_As&&>(__as)...); + } - template - void set_error(_Error&& __err) noexcept { - stdexec::set_error(static_cast<_Receiver&&>(__rcvr_), static_cast<_Error&&>(__err)); - } + template + void set_error(_Error&& __err) noexcept { + stdexec::set_error(static_cast<_Receiver&&>(__rcvr_), static_cast<_Error&&>(__err)); + } - void set_stopped() noexcept { - stdexec::set_stopped(static_cast<_Receiver&&>(__rcvr_)); - } + void set_stopped() noexcept { + stdexec::set_stopped(static_cast<_Receiver&&>(__rcvr_)); + } - auto get_env() const noexcept { - return __env::__join( - prop{get_scheduler, __sched_}, __env::__without(stdexec::get_env(__rcvr_), get_domain)); - } + auto get_env() const noexcept { + return __env::__join(__sched_env{__sched_}, stdexec::get_env(__rcvr_)); + } + }; }; template - __receiver_with_sched(_Receiver, _Scheduler) -> __receiver_with_sched<_Receiver, _Scheduler>; + using __receiver_with_sched_t = __t<__rcvr_sch<__id<_Receiver>, __id<_Scheduler>>>; // If the input sender knows its completion scheduler, make it the current scheduler // in the environment seen by the result sender. @@ -128,9 +133,7 @@ namespace stdexec { using __result_env_t = __if_c< __is_scheduler_affine>, _Env, - __env::__join_t< // - prop, - __env::__without_t<_Env, get_domain_t>>>; + __env::__join_t<__sched_env<_Scheduler>, _Env>>; template <__mstring _Where, __mstring _What> struct _FUNCTION_MUST_RETURN_A_VALID_SENDER_IN_THE_CURRENT_ENVIRONMENT_ { }; @@ -188,7 +191,7 @@ namespace stdexec { using __result_receiver_t = __if_c< __is_scheduler_affine>, _Receiver, - __receiver_with_sched<_Receiver, _Scheduler>>; + __receiver_with_sched_t<_Receiver, _Scheduler>>; template using __receiver_ref_t = // @@ -312,8 +315,8 @@ namespace stdexec { return (__env); } else { return __env::__join( - prop{get_scheduler, get_completion_scheduler<_Set>(stdexec::get_env(__child))}, - __env::__without(static_cast<_Env&&>(__env), get_domain)); + __sched_env{get_completion_scheduler<_Set>(stdexec::get_env(__child))}, + static_cast<_Env&&>(__env)); } } }; @@ -366,6 +369,7 @@ namespace stdexec { using __fun_t = _Fun; using __sched_t = _Sched; using __env_t = __result_env_t<_Sched, env_of_t<_Receiver>>; + using __rcvr_t = __receiver_with_sched_t<_Receiver, _Sched>; using __result_variant = __variant_for<__monostate, _Tuples...>; using __op_state_variant = // __variant_for< @@ -382,7 +386,7 @@ namespace stdexec { if constexpr (__is_scheduler_affine>) { return static_cast<_Receiver&&>(__rcvr); } else { - return __receiver_with_sched{static_cast<_Receiver&&>(__rcvr), this->__sched_}; + return __rcvr_t{static_cast<_Receiver&&>(__rcvr), this->__sched_}; } } } @@ -391,8 +395,7 @@ namespace stdexec { if constexpr (__is_scheduler_affine>) { return stdexec::get_env(__rcvr); } else { - return __env::__join( - prop{get_scheduler, __sched_}, __env::__without(stdexec::get_env(__rcvr), get_domain)); + return __env::__join(__sched_env{__sched_}, stdexec::get_env(__rcvr)); } } diff --git a/include/stdexec/__detail/__meta.hpp b/include/stdexec/__detail/__meta.hpp index 21804a635..b474f9e62 100644 --- a/include/stdexec/__detail/__meta.hpp +++ b/include/stdexec/__detail/__meta.hpp @@ -19,7 +19,6 @@ #include #include #include -#include #include "__config.hpp" #include "__concepts.hpp" @@ -79,7 +78,7 @@ namespace stdexec { // nvbugs#4679848 and nvbugs#4668709 also preclude __mconstant from representing a compile-time // size_t. - enum class __muchar : unsigned char { + enum class __u8 : unsigned char { }; #if STDEXEC_NVCC() || STDEXEC_EDG() @@ -90,7 +89,7 @@ namespace stdexec { using __msize_t = __mconstant<_Np>; #else template - using __msize_t = __muchar (*)[_Np + 1]; // +1 to avoid zero-size array + using __msize_t = __u8 (*)[_Np + 1]; // +1 to avoid zero-size array #endif //! Metafunction selects the first of two type arguments. @@ -126,15 +125,13 @@ namespace stdexec { inline constexpr auto __v<__mconstant<_Np>> = _Np; template - inline constexpr std::size_t __v<__muchar (*)[_Np]> = _Np - 1; // see definition of __msize_t + inline constexpr std::size_t __v<__u8 (*)[_Np]> = _Np - 1; // see definition of __msize_t - namespace __pack { - template - struct __t; - } // namespace __pack + template + struct __iota; template - using __indices = __pack::__t<_Is...> *; + using __indices = __iota<_Is...> *; #if STDEXEC_MSVC() namespace __pack { @@ -686,7 +683,7 @@ namespace stdexec { }; template - struct __muncurry_<__pack::__t<_Ns...> *> { + struct __muncurry_<__indices<_Ns...>> { template using __f = __minvoke<_Fn, __msize_t<_Ns>...>; }; diff --git a/include/stdexec/__detail/__on.hpp b/include/stdexec/__detail/__on.hpp index 94937c2ab..85e9dd867 100644 --- a/include/stdexec/__detail/__on.hpp +++ b/include/stdexec/__detail/__on.hpp @@ -127,7 +127,8 @@ namespace stdexec { STDEXEC_ATTRIBUTE((always_inline)) static auto __transform_env_fn(_Env&& __env) noexcept { return [&](__ignore, _Data&& __data, __ignore) noexcept -> decltype(auto) { if constexpr (scheduler<_Data>) { - return __detail::__mkenv_sched(static_cast<_Env&&>(__env), static_cast<_Data&&>(__data)); + return __env::__join( + __sched_env{static_cast<_Data&&>(__data)}, static_cast<_Env&&>(__env)); } else { return static_cast<_Env>(static_cast<_Env&&>(__env)); } diff --git a/include/stdexec/__detail/__schedule_from.hpp b/include/stdexec/__detail/__schedule_from.hpp index 2e91432c5..ed0815600 100644 --- a/include/stdexec/__detail/__schedule_from.hpp +++ b/include/stdexec/__detail/__schedule_from.hpp @@ -111,31 +111,41 @@ namespace stdexec { // the source sender completes, the completion information is saved off in the operation state // so that when this receiver completes, it can read the completion out of the operation state // and forward it to the output receiver after transitioning to the scheduler's context. - template - struct __receiver2 { - using receiver_concept = receiver_t; - - void set_value() noexcept { - __state_->__data_.visit(__schfr::__make_visitor_fn(__state_), __state_->__data_); - } + template + struct __rcvr2 { + using _Scheduler = stdexec::__t<_SchedulerId>; + using _Sexpr = stdexec::__t<_SexprId>; + using _Receiver = stdexec::__t<_ReceiverId>; + + struct __t { + using receiver_concept = receiver_t; + using __id = __rcvr2; + + void set_value() noexcept { + __state_->__data_.visit(__schfr::__make_visitor_fn(__state_), __state_->__data_); + } - template - void set_error(_Error&& __err) noexcept { - stdexec::set_error( - static_cast<_Receiver&&>(__state_->__receiver()), static_cast<_Error&&>(__err)); - } + template + void set_error(_Error&& __err) noexcept { + stdexec::set_error( + static_cast<_Receiver&&>(__state_->__receiver()), static_cast<_Error&&>(__err)); + } - void set_stopped() noexcept { - stdexec::set_stopped(static_cast<_Receiver&&>(__state_->__receiver())); - } + void set_stopped() noexcept { + stdexec::set_stopped(static_cast<_Receiver&&>(__state_->__receiver())); + } - auto get_env() const noexcept -> env_of_t<_Receiver> { - return stdexec::get_env(__state_->__receiver()); - } + auto get_env() const noexcept -> env_of_t<_Receiver> { + return stdexec::get_env(__state_->__receiver()); + } - __state<_Scheduler, _Sexpr, _Receiver>* __state_; + __state<_Scheduler, _Sexpr, _Receiver>* __state_; + }; }; + template + using __receiver2 = __t<__rcvr2<__id<_Scheduler>, __id<_Sexpr>, __id<_Receiver>>>; + template struct __state : __enable_receiver_from_this<_Sexpr, _Receiver, __state<_Scheduler, _Sexpr, _Receiver>> diff --git a/include/stdexec/__detail/__schedulers.hpp b/include/stdexec/__detail/__schedulers.hpp index cfb0f49eb..9b963aef0 100644 --- a/include/stdexec/__detail/__schedulers.hpp +++ b/include/stdexec/__detail/__schedulers.hpp @@ -116,18 +116,4 @@ namespace stdexec { return tag_invoke(*this, __env); } } // namespace __queries - - namespace __detail { - // A handy utility for augmenting an environment with a scheduler. - template - STDEXEC_ATTRIBUTE((always_inline)) auto __mkenv_sched(_Env&& __env, _Scheduler __sched) { - auto __env2 = __env::__join( - prop{get_scheduler, __sched}, __env::__without(static_cast<_Env&&>(__env), get_domain)); - using _Env2 = decltype(__env2); - - struct __env_t : _Env2 { }; - - return __env_t{static_cast<_Env2&&>(__env2)}; - } - } // namespace __detail } // namespace stdexec diff --git a/include/stdexec/__detail/__starts_on.hpp b/include/stdexec/__detail/__starts_on.hpp index e21d37c29..672218a66 100644 --- a/include/stdexec/__detail/__starts_on.hpp +++ b/include/stdexec/__detail/__starts_on.hpp @@ -23,7 +23,6 @@ #include "__domain.hpp" #include "__env.hpp" #include "__let.hpp" -#include "__meta.hpp" #include "__schedulers.hpp" #include "__senders_core.hpp" #include "__transform_sender.hpp" @@ -61,7 +60,7 @@ namespace stdexec { template STDEXEC_ATTRIBUTE((always_inline)) static auto __transform_env_fn(_Env&& __env) noexcept { return [&](__ignore, auto __sched, __ignore) noexcept { - return __detail::__mkenv_sched(static_cast<_Env&&>(__env), __sched); + return __env::__join(__sched_env{__sched}, static_cast<_Env&&>(__env)); }; }