@@ -36,76 +36,69 @@ STDEXEC_PRAGMA_IGNORE_MSVC(4702) // warning C4702: unreachable code
3636namespace STDEXEC {
3737 class task_scheduler ;
3838
39- // namespace __detail {
40- // struct __env_proxy : __immovable {
41- // [[nodiscard]]
42- // virtual auto query(const get_stop_token_t&) const noexcept -> inplace_stop_token = 0;
43- // [[nodiscard]]
44- // virtual auto query(const get_allocator_t&) const noexcept -> __any_allocator<std::byte> = 0;
45- // [[nodiscard]]
46- // virtual auto query(const get_scheduler_t&) const noexcept -> task_scheduler = 0;
47- // };
48- // } // namespace __detail
49-
5039 namespace system_context_replaceability {
5140 // / Interface for completing a sender operation. Backend will call frontend though
5241 // / this interface for completing the `schedule` and `schedule_bulk` operations.
5342 class receiver_proxy { // : __detail::__env_proxy {
5443 public:
55- virtual ~receiver_proxy () = 0 ;
56-
57- virtual void set_value () noexcept = 0;
58- virtual void set_error (std::exception_ptr&&) noexcept = 0;
59- virtual void set_stopped () noexcept = 0;
44+ virtual constexpr ~receiver_proxy () = 0 ;
6045
61- // // NOT TO SPEC:
62- // [[nodiscard]]
63- // auto get_env() const noexcept -> const __detail::__env_proxy& {
64- // return *this;
65- // }
46+ virtual constexpr void set_value () noexcept = 0;
47+ virtual STDEXEC_CONSTEXPR_CXX23 void set_error (std::exception_ptr) noexcept = 0;
48+ virtual constexpr void set_stopped () noexcept = 0;
6649
6750 // / Query the receiver for a property of type `_P`.
68- template <class _P , __class _Query>
69- auto try_query (_Query) const noexcept -> std::optional<_P > {
70- std::optional<_P > __p;
71- __query_env (__mtypeid<_Query>, __mtypeid<_P >, &__p);
51+ template <class _Value , __class _Query>
52+ constexpr auto try_query (_Query) const noexcept -> std::optional<_Value > {
53+ std::optional<_Value > __p;
54+ __query_env (__mtypeid<_Query>, __mtypeid<_Value >, &__p);
7255 return __p;
7356 }
7457
7558 protected:
76- virtual void __query_env (__type_index, __type_index, void *) const noexcept = 0;
59+ virtual constexpr void __query_env (__type_index, __type_index, void *) const noexcept = 0;
7760 };
7861
79- inline receiver_proxy::~receiver_proxy () = default ;
62+ inline constexpr receiver_proxy::~receiver_proxy () = default ;
8063
8164 struct bulk_item_receiver_proxy : receiver_proxy {
82- virtual void execute (size_t , size_t ) noexcept = 0;
65+ virtual constexpr void execute (size_t , size_t ) noexcept = 0;
8366 };
8467
8568 // / Interface for the parallel scheduler backend.
8669 struct parallel_scheduler_backend {
87- virtual ~parallel_scheduler_backend () = 0 ;
70+ virtual constexpr ~parallel_scheduler_backend () = 0 ;
71+
72+ // / Future-proofing: in case we need to add more virtual functions, we can use this
73+ // / to query for additional interfaces without breaking ABI.
74+ [[nodiscard]]
75+ virtual constexpr auto __query_interface (__type_index __id) const noexcept -> void* {
76+ if (__id == __mtypeid<parallel_scheduler_backend>) {
77+ return const_cast <parallel_scheduler_backend*>(this );
78+ }
79+ return nullptr ;
80+ }
8881
8982 // / Schedule work on parallel scheduler, calling `__r` when done and using `__s` for preallocated
9083 // / memory.
91- virtual void schedule (receiver_proxy&, std::span<std::byte>) noexcept = 0;
84+ virtual constexpr void schedule (receiver_proxy&, std::span<std::byte>) noexcept = 0;
9285
9386 // / Schedule bulk work of size `__n` on parallel scheduler, calling `__r` for different
9487 // / subranges of [0, __n), and using `__s` for preallocated memory.
95- virtual void schedule_bulk_chunked (
88+ virtual constexpr void schedule_bulk_chunked (
9689 std::size_t ,
9790 bulk_item_receiver_proxy&,
9891 std::span<std::byte>) noexcept = 0;
9992
10093 // / Schedule bulk work of size `__n` on parallel scheduler, calling `__r` for each item, and
10194 // / using `__s` for preallocated memory.
102- virtual void schedule_bulk_unchunked (
95+ virtual constexpr void schedule_bulk_unchunked (
10396 std::size_t ,
10497 bulk_item_receiver_proxy&,
10598 std::span<std::byte>) noexcept = 0;
10699 };
107100
108- inline parallel_scheduler_backend::~parallel_scheduler_backend () = default ;
101+ inline constexpr parallel_scheduler_backend::~parallel_scheduler_backend () = default ;
109102 } // namespace system_context_replaceability
110103
111104 namespace __detail {
@@ -116,20 +109,20 @@ namespace STDEXEC {
116109 public:
117110 using receiver_concept = receiver_t ;
118111
119- explicit __receiver_proxy_base (_Rcvr rcvr) noexcept
112+ constexpr explicit __receiver_proxy_base (_Rcvr rcvr) noexcept
120113 : __rcvr_(static_cast <_Rcvr&&>(rcvr)) {
121114 }
122115
123- void set_error (std::exception_ptr&& eptr) noexcept final {
116+ STDEXEC_CONSTEXPR_CXX23 void set_error (std::exception_ptr eptr) noexcept final {
124117 STDEXEC::set_error (std::move (__rcvr_), std::move (eptr));
125118 }
126119
127- void set_stopped () noexcept final {
120+ constexpr void set_stopped () noexcept final {
128121 STDEXEC::set_stopped (std::move (__rcvr_));
129122 }
130123
131124 protected:
132- void __query_env (__type_index __query_id, __type_index __value, void * __dest)
125+ constexpr void __query_env (__type_index __query_id, __type_index __value, void * __dest)
133126 const noexcept final {
134127 if (__query_id == __mtypeid<get_stop_token_t >) {
135128 __query (get_stop_token, __value, __dest);
@@ -139,7 +132,7 @@ namespace STDEXEC {
139132 }
140133
141134 private:
142- void __query (get_stop_token_t , __type_index __value_type, void * __dest) const noexcept {
135+ constexpr void __query (get_stop_token_t , __type_index __value_type, void * __dest) const noexcept {
143136 using __stop_token_t = stop_token_of_t <env_of_t <_Rcvr>>;
144137 if constexpr (std::is_same_v<inplace_stop_token, __stop_token_t >) {
145138 if (__value_type == __mtypeid<inplace_stop_token>) {
@@ -149,7 +142,7 @@ namespace STDEXEC {
149142 }
150143 }
151144
152- void __query (get_allocator_t , __type_index __value_type, void * __dest) const noexcept {
145+ constexpr void __query (get_allocator_t , __type_index __value_type, void * __dest) const noexcept {
153146 if (__value_type == __mtypeid<__any_allocator<std::byte>>) {
154147 using __dest_t = std::optional<__any_allocator<std::byte>>;
155148 constexpr auto __get_alloc = __with_default (get_allocator, std::allocator<std::byte>());
@@ -159,39 +152,16 @@ namespace STDEXEC {
159152 }
160153 }
161154
162- // [[nodiscard]]
163- // auto query(const get_stop_token_t&) const noexcept -> inplace_stop_token final {
164- // if constexpr (__callable<const get_stop_token_t&, env_of_t<_Rcvr>>) {
165- // if constexpr (__same_as<stop_token_of_t<env_of_t<_Rcvr>>, inplace_stop_token>) {
166- // return get_stop_token(get_env(__rcvr_));
167- // }
168- // }
169- // return inplace_stop_token{}; // MSVC thinks this is unreachable. :-?
170- // }
171-
172- // [[nodiscard]]
173- // auto query(const get_allocator_t&) const noexcept -> any_allocator<std::byte> final {
174- // return any_allocator{
175- // __with_default(get_allocator, std::allocator<std::byte>())(get_env(__rcvr_))};
176- // }
177-
178- // // defined in task_scheduler.cuh:
179- // [[nodiscard]]
180- // auto query(const get_scheduler_t& __query) const noexcept -> task_scheduler final;
181-
182155 public:
183156 _Rcvr __rcvr_;
184157 };
185158
186159 template <class _Rcvr >
187160 struct __receiver_proxy
188161 : __receiver_proxy_base<_Rcvr, system_context_replaceability::receiver_proxy> {
189- using __receiver_proxy_base<
190- _Rcvr,
191- system_context_replaceability::receiver_proxy
192- >::__receiver_proxy_base;
162+ using __receiver_proxy::__receiver_proxy_base::__receiver_proxy_base;
193163
194- void set_value () noexcept final {
164+ constexpr void set_value () noexcept final {
195165 STDEXEC::set_value (std::move (this ->__rcvr_ ));
196166 }
197167 };
@@ -205,26 +175,26 @@ namespace STDEXEC {
205175 using receiver_concept = receiver_t ;
206176 using __delete_fn_t = void (void *) noexcept ;
207177
208- void set_value () noexcept {
178+ constexpr void set_value () noexcept {
209179 auto & __proxy = __rcvr_proxy_;
210180 __delete_fn_ (__opstate_storage_); // NB: destroys *this
211181 __proxy.set_value ();
212182 }
213183
214- void set_error (std::exception_ptr eptr ) noexcept {
184+ STDEXEC_CONSTEXPR_CXX23 void set_error (std::exception_ptr __eptr ) noexcept {
215185 auto & __proxy = __rcvr_proxy_;
216186 __delete_fn_ (__opstate_storage_); // NB: destroys *this
217- __proxy.set_error (std::move (eptr ));
187+ __proxy.set_error (std::move (__eptr ));
218188 }
219189
220- void set_stopped () noexcept {
190+ constexpr void set_stopped () noexcept {
221191 auto & __proxy = __rcvr_proxy_;
222192 __delete_fn_ (__opstate_storage_); // NB: destroys *this
223193 __proxy.set_stopped ();
224194 }
225195
226196 [[nodiscard]]
227- auto get_env () const noexcept -> env_of_t<_RcvrProxy> {
197+ constexpr auto get_env () const noexcept -> env_of_t<_RcvrProxy> {
228198 return STDEXEC::get_env (__rcvr_proxy_);
229199 }
230200
0 commit comments