3333STDEXEC_PRAGMA_PUSH ()
3434STDEXEC_PRAGMA_IGNORE_MSVC(4702 ) // warning C4702: unreachable code
3535
36+ // For weak linking to work on Windows, we must leave query_parallel_scheduler_backend
37+ // undefined, and in a separate translation unit, provide a default implementation with a
38+ // different name, and then use a linker directive to alias the weak symbol to the default
39+ // implementation. For this, it is necessary to utter the mangled names of both
40+ // query_parallel_scheduler_backend and __default_query_parallel_scheduler_backend. We
41+ // don't want the mangled name to depend on the value of the STDEXEC macro, so we put both
42+ // functions in a separate namespace.
43+ #if STDEXEC_MSVC()
44+ namespace STDEXEC ::system_context_replaceability {
45+ }
46+ namespace __system_context_replaceability {
47+ using namespace STDEXEC ::system_context_replaceability;
48+ } // namespace __system_context_replaceability
49+ namespace STDEXEC ::system_context_replaceability {
50+ using namespace ::__system_context_replaceability;
51+ } // namespace STDEXEC::system_context_replaceability
52+ # define STDEXEC_SYSTEM_CONTEXT_REPLACEABILITY_NAMESPACE __system_context_replaceability
53+ #else
54+ # define STDEXEC_SYSTEM_CONTEXT_REPLACEABILITY_NAMESPACE STDEXEC::system_context_replaceability
55+ #endif
56+
3657namespace STDEXEC {
3758 class task_scheduler ;
3859
@@ -95,9 +116,7 @@ namespace STDEXEC {
95116// Give parallel_scheduler_backend a mangled name that does not depend on the value of the
96117// STDEXEC macro. This is so that we can use weak linking to make
97118// query_parallel_scheduler_backend replaceable.
98- namespace __system_context_replaceability {
99- using namespace STDEXEC ::system_context_replaceability;
100-
119+ namespace STDEXEC_SYSTEM_CONTEXT_REPLACEABILITY_NAMESPACE {
101120 // / Interface for the parallel scheduler backend.
102121 struct parallel_scheduler_backend : __parallel_scheduler_backend_base {
103122 // / Schedule work on parallel scheduler, calling `__r` when done and using `__s` for preallocated
@@ -118,138 +137,132 @@ namespace __system_context_replaceability {
118137 bulk_item_receiver_proxy&,
119138 std::span<std::byte>) noexcept = 0;
120139 };
121- } // namespace __system_context_replaceability
122-
123- namespace STDEXEC {
124- namespace system_context_replaceability {
125- using namespace ::__system_context_replaceability;
126- } // namespace system_context_replaceability
127-
128- namespace __detail {
129- // Partially implements the _RcvrProxy interface (either receiver_proxy or
130- // bulk_item_receiver_proxy) in terms of a concrete receiver type _Rcvr.
131- template <class _Rcvr , class _RcvrProxy >
132- struct __receiver_proxy_base : _RcvrProxy {
133- public:
134- using receiver_concept = receiver_t ;
135-
136- explicit __receiver_proxy_base (_Rcvr rcvr) noexcept
137- : __rcvr_(static_cast <_Rcvr&&>(rcvr)) {
138- }
139-
140- void set_error (std::exception_ptr&& eptr) noexcept final {
141- STDEXEC::set_error (std::move (__rcvr_), std::move (eptr));
142- }
143-
144- void set_stopped () noexcept final {
145- STDEXEC::set_stopped (std::move (__rcvr_));
146- }
147-
148- protected:
149- void __query_env (__type_index __query_id, __type_index __value, void * __dest)
150- const noexcept final {
151- if (__query_id == __mtypeid<get_stop_token_t >) {
152- __query (get_stop_token, __value, __dest);
153- } else if (__query_id == __mtypeid<get_allocator_t >) {
154- __query (get_allocator, __value, __dest);
155- }
140+ } // namespace STDEXEC_SYSTEM_CONTEXT_REPLACEABILITY_NAMESPACE
141+
142+ namespace STDEXEC ::__detail {
143+ // Partially implements the _RcvrProxy interface (either receiver_proxy or
144+ // bulk_item_receiver_proxy) in terms of a concrete receiver type _Rcvr.
145+ template <class _Rcvr , class _RcvrProxy >
146+ struct __receiver_proxy_base : _RcvrProxy {
147+ public:
148+ using receiver_concept = receiver_t ;
149+
150+ explicit __receiver_proxy_base (_Rcvr rcvr) noexcept
151+ : __rcvr_(static_cast <_Rcvr&&>(rcvr)) {
152+ }
153+
154+ void set_error (std::exception_ptr&& eptr) noexcept final {
155+ STDEXEC::set_error (std::move (__rcvr_), std::move (eptr));
156+ }
157+
158+ void set_stopped () noexcept final {
159+ STDEXEC::set_stopped (std::move (__rcvr_));
160+ }
161+
162+ protected:
163+ void __query_env (__type_index __query_id, __type_index __value, void * __dest)
164+ const noexcept final {
165+ if (__query_id == __mtypeid<get_stop_token_t >) {
166+ __query (get_stop_token, __value, __dest);
167+ } else if (__query_id == __mtypeid<get_allocator_t >) {
168+ __query (get_allocator, __value, __dest);
156169 }
157-
158- private:
159- void __query (get_stop_token_t , __type_index __value_type, void * __dest) const noexcept {
160- using __stop_token_t = stop_token_of_t <env_of_t <_Rcvr>>;
161- if constexpr (std::is_same_v<inplace_stop_token, __stop_token_t >) {
162- if (__value_type == __mtypeid<inplace_stop_token>) {
163- using __dest_t = std::optional<inplace_stop_token>;
164- *static_cast <__dest_t *>(__dest) = STDEXEC::get_stop_token (STDEXEC::get_env (__rcvr_));
165- }
166- }
167- }
168-
169- void __query (get_allocator_t , __type_index __value_type, void * __dest) const noexcept {
170- if (__value_type == __mtypeid<__any_allocator<std::byte>>) {
171- using __dest_t = std::optional<__any_allocator<std::byte>>;
172- constexpr auto __get_alloc = __with_default (get_allocator, std::allocator<std::byte>());
173- auto __alloc = STDEXEC::__rebind_allocator<std::byte>(
174- __get_alloc (STDEXEC::get_env (__rcvr_)));
175- *static_cast <__dest_t *>(__dest) = __any_allocator{std::move (__alloc)};
170+ }
171+
172+ private:
173+ void __query (get_stop_token_t , __type_index __value_type, void * __dest) const noexcept {
174+ using __stop_token_t = stop_token_of_t <env_of_t <_Rcvr>>;
175+ if constexpr (std::is_same_v<inplace_stop_token, __stop_token_t >) {
176+ if (__value_type == __mtypeid<inplace_stop_token>) {
177+ using __dest_t = std::optional<inplace_stop_token>;
178+ *static_cast <__dest_t *>(__dest) = STDEXEC::get_stop_token (STDEXEC::get_env (__rcvr_));
176179 }
177180 }
178-
179- // [[nodiscard]]
180- // auto query(const get_stop_token_t&) const noexcept -> inplace_stop_token final {
181- // if constexpr (__callable<const get_stop_token_t&, env_of_t<_Rcvr>>) {
182- // if constexpr (__same_as<stop_token_of_t<env_of_t<_Rcvr>>, inplace_stop_token>) {
183- // return get_stop_token(get_env(__rcvr_));
184- // }
185- // }
186- // return inplace_stop_token{}; // MSVC thinks this is unreachable. :-?
187- // }
188-
189- // [[nodiscard]]
190- // auto query(const get_allocator_t&) const noexcept -> any_allocator<std::byte> final {
191- // return any_allocator{
192- // __with_default(get_allocator, std::allocator<std::byte>())(get_env(__rcvr_))};
193- // }
194-
195- // // defined in task_scheduler.cuh:
196- // [[nodiscard]]
197- // auto query(const get_scheduler_t& __query) const noexcept -> task_scheduler final;
198-
199- public:
200- _Rcvr __rcvr_;
201- };
202-
203- template <class _Rcvr >
204- struct __receiver_proxy
205- : __receiver_proxy_base<_Rcvr, system_context_replaceability::receiver_proxy> {
206- using __receiver_proxy_base<
207- _Rcvr,
208- system_context_replaceability::receiver_proxy
209- >::__receiver_proxy_base;
210-
211- void set_value () noexcept final {
212- STDEXEC::set_value (std::move (this ->__rcvr_ ));
213- }
214- };
215-
216- // A receiver type that forwards its completion operations to a _RcvrProxy member held
217- // by reference (where _RcvrProxy is one of receiver_proxy or
218- // bulk_item_receiver_proxy). It is also responsible for destroying and, if necessary,
219- // deallocating the operation state.
220- template <class _RcvrProxy >
221- struct __proxy_receiver {
222- using receiver_concept = receiver_t ;
223- using __delete_fn_t = void (void *) noexcept ;
224-
225- void set_value () noexcept {
226- auto & __proxy = __rcvr_proxy_;
227- __delete_fn_ (__opstate_storage_); // NB: destroys *this
228- __proxy.set_value ();
229- }
230-
231- void set_error (std::exception_ptr eptr) noexcept {
232- auto & __proxy = __rcvr_proxy_;
233- __delete_fn_ (__opstate_storage_); // NB: destroys *this
234- __proxy.set_error (std::move (eptr));
235- }
236-
237- void set_stopped () noexcept {
238- auto & __proxy = __rcvr_proxy_;
239- __delete_fn_ (__opstate_storage_); // NB: destroys *this
240- __proxy.set_stopped ();
181+ }
182+
183+ void __query (get_allocator_t , __type_index __value_type, void * __dest) const noexcept {
184+ if (__value_type == __mtypeid<__any_allocator<std::byte>>) {
185+ using __dest_t = std::optional<__any_allocator<std::byte>>;
186+ constexpr auto __get_alloc = __with_default (get_allocator, std::allocator<std::byte>());
187+ auto __alloc = STDEXEC::__rebind_allocator<std::byte>(
188+ __get_alloc (STDEXEC::get_env (__rcvr_)));
189+ *static_cast <__dest_t *>(__dest) = __any_allocator{std::move (__alloc)};
241190 }
191+ }
192+
193+ // [[nodiscard]]
194+ // auto query(const get_stop_token_t&) const noexcept -> inplace_stop_token final {
195+ // if constexpr (__callable<const get_stop_token_t&, env_of_t<_Rcvr>>) {
196+ // if constexpr (__same_as<stop_token_of_t<env_of_t<_Rcvr>>, inplace_stop_token>) {
197+ // return get_stop_token(get_env(__rcvr_));
198+ // }
199+ // }
200+ // return inplace_stop_token{}; // MSVC thinks this is unreachable. :-?
201+ // }
202+
203+ // [[nodiscard]]
204+ // auto query(const get_allocator_t&) const noexcept -> any_allocator<std::byte> final {
205+ // return any_allocator{
206+ // __with_default(get_allocator, std::allocator<std::byte>())(get_env(__rcvr_))};
207+ // }
208+
209+ // // defined in task_scheduler.cuh:
210+ // [[nodiscard]]
211+ // auto query(const get_scheduler_t& __query) const noexcept -> task_scheduler final;
212+
213+ public:
214+ _Rcvr __rcvr_;
215+ };
242216
243- [[nodiscard]]
244- auto get_env () const noexcept -> env_of_t<_RcvrProxy> {
245- return STDEXEC::get_env (__rcvr_proxy_);
246- }
217+ template <class _Rcvr >
218+ struct __receiver_proxy
219+ : __receiver_proxy_base<_Rcvr, system_context_replaceability::receiver_proxy> {
220+ using __receiver_proxy_base<
221+ _Rcvr,
222+ system_context_replaceability::receiver_proxy
223+ >::__receiver_proxy_base;
224+
225+ void set_value () noexcept final {
226+ STDEXEC::set_value (std::move (this ->__rcvr_ ));
227+ }
228+ };
247229
248- _RcvrProxy& __rcvr_proxy_;
249- void * __opstate_storage_;
250- __delete_fn_t * __delete_fn_;
251- };
252- } // namespace __detail
253- } // namespace STDEXEC
230+ // A receiver type that forwards its completion operations to a _RcvrProxy member held
231+ // by reference (where _RcvrProxy is one of receiver_proxy or
232+ // bulk_item_receiver_proxy). It is also responsible for destroying and, if necessary,
233+ // deallocating the operation state.
234+ template <class _RcvrProxy >
235+ struct __proxy_receiver {
236+ using receiver_concept = receiver_t ;
237+ using __delete_fn_t = void (void *) noexcept ;
238+
239+ void set_value () noexcept {
240+ auto & __proxy = __rcvr_proxy_;
241+ __delete_fn_ (__opstate_storage_); // NB: destroys *this
242+ __proxy.set_value ();
243+ }
244+
245+ void set_error (std::exception_ptr eptr) noexcept {
246+ auto & __proxy = __rcvr_proxy_;
247+ __delete_fn_ (__opstate_storage_); // NB: destroys *this
248+ __proxy.set_error (std::move (eptr));
249+ }
250+
251+ void set_stopped () noexcept {
252+ auto & __proxy = __rcvr_proxy_;
253+ __delete_fn_ (__opstate_storage_); // NB: destroys *this
254+ __proxy.set_stopped ();
255+ }
256+
257+ [[nodiscard]]
258+ auto get_env () const noexcept -> env_of_t<_RcvrProxy> {
259+ return STDEXEC::get_env (__rcvr_proxy_);
260+ }
261+
262+ _RcvrProxy& __rcvr_proxy_;
263+ void * __opstate_storage_;
264+ __delete_fn_t * __delete_fn_;
265+ };
266+ } // namespace STDEXEC::__detail
254267
255268STDEXEC_PRAGMA_POP ()
0 commit comments