Skip to content

Commit 61707d2

Browse files
authored
fix domain query of __sched_env (#1905)
* fix domain query of `__sched_env`
1 parent 2ec956d commit 61707d2

File tree

7 files changed

+164
-101
lines changed

7 files changed

+164
-101
lines changed

include/stdexec/__detail/__finally.hpp

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
// include these after execution_fwd.hpp
2222
#include "__basic_sender.hpp"
2323
#include "__optional.hpp"
24+
#include "__schedulers.hpp"
2425
#include "__sender_adaptor_closure.hpp"
2526
#include "__senders.hpp"
2627
#include "__transform_completion_signatures.hpp"
@@ -64,8 +65,8 @@ namespace STDEXEC
6465
transform_sender(STDEXEC::set_value_t, _Sender&& __sndr, STDEXEC::__ignore)
6566
{
6667
auto& [__tag, __ign, __initial, __final] = __sndr;
67-
return __final ::__sender{STDEXEC::__forward_like<_Sender>(__initial), //
68-
STDEXEC::__forward_like<_Sender>(__final)};
68+
return STDEXEC::__final::__sender{STDEXEC::__forward_like<_Sender>(__initial), //
69+
STDEXEC::__forward_like<_Sender>(__final)};
6970
}
7071
};
7172

@@ -98,10 +99,12 @@ namespace STDEXEC
9899
_CvInitialSender,
99100
_Receiver>;
100101

101-
template <class _ResultType, class _Receiver>
102+
template <class _ResultType, class _Receiver, class _Env2>
102103
struct __opstate_base
103104
{
104-
_Receiver __rcvr_{};
105+
_Receiver __rcvr_{};
106+
STDEXEC_ATTRIBUTE(no_unique_address)
107+
_Env2 const __env2_{};
105108
_ResultType __result_{__no_init}; // __variant<__tuple<set_tag, args...>, ...>
106109
};
107110

@@ -123,10 +126,11 @@ namespace STDEXEC
123126
}
124127
};
125128

126-
template <class _ResultType, class _Receiver>
129+
template <class _ResultType, class _Receiver, class _Env2>
127130
struct __final_receiver
128131
{
129132
using receiver_concept = receiver_t;
133+
using __env2_t = __join_env_t<_Env2 const &, __fwd_env_t<env_of_t<_Receiver>>>;
130134

131135
constexpr void set_value() noexcept
132136
{
@@ -146,26 +150,28 @@ namespace STDEXEC
146150
}
147151

148152
[[nodiscard]]
149-
constexpr auto get_env() const noexcept -> __fwd_env_t<env_of_t<_Receiver>>
153+
constexpr auto get_env() const noexcept -> __env2_t
150154
{
151-
return __fwd_env(STDEXEC::get_env(__opstate_->__rcvr_));
155+
return __env::__join(__opstate_->__env2_, __fwd_env(STDEXEC::get_env(__opstate_->__rcvr_)));
152156
}
153157

154-
__opstate_base<_ResultType, _Receiver>* __opstate_;
158+
__opstate_base<_ResultType, _Receiver, _Env2>* __opstate_;
155159
};
156160

157-
template <class _CvFinalSender, class _ResultType, class _Receiver>
158-
struct __final_opstate : __opstate_base<_ResultType, _Receiver>
161+
template <class _CvFinalSender, class _ResultType, class _Receiver, class _Env2>
162+
struct __final_opstate : __opstate_base<_ResultType, _Receiver, _Env2>
159163
{
160164
using __results_t = _ResultType;
161165
using __cleanup_callback_t = void(__final_opstate*) noexcept;
162-
using __final_receiver_t = __final_receiver<_ResultType, _Receiver>;
166+
using __final_receiver_t = __final_receiver<_ResultType, _Receiver, _Env2>;
163167
using __final_opstate_t = connect_result_t<_CvFinalSender, __final_receiver_t>;
164168

165169
constexpr explicit __final_opstate(__cleanup_callback_t* __cleanup_callback,
166170
_CvFinalSender&& __final,
167-
_Receiver&& __rcvr) noexcept
168-
: __opstate_base<_ResultType, _Receiver>{static_cast<_Receiver&&>(__rcvr)}
171+
_Receiver&& __rcvr,
172+
_Env2 __env2) noexcept
173+
: __opstate_base<_ResultType, _Receiver, _Env2>{static_cast<_Receiver&&>(__rcvr),
174+
static_cast<_Env2&&>(__env2)}
169175
, __cleanup_callback_{__cleanup_callback}
170176
, __final_opstate_(
171177
STDEXEC::connect(static_cast<_CvFinalSender&&>(__final), __final_receiver_t{this}))
@@ -205,27 +211,40 @@ namespace STDEXEC
205211
__final_opstate_t __final_opstate_;
206212
};
207213

208-
template <class _CvFinalSender, class _ResultType, class _Receiver>
214+
template <class _CvFinalSender, class _ResultType, class _Receiver, class _Env2>
209215
struct __initial_receiver;
210216

211-
template <class _CvInitialSender, class _CvFinalSender, class _Receiver>
217+
template <class _CvInitialSender, class _CvFinalSender, class _Receiver, class _Env2>
212218
using __final_opstate_t =
213219
__final_opstate<_CvFinalSender,
214220
__result_variant_t<_CvInitialSender, _CvFinalSender, _Receiver>,
215-
_Receiver>;
221+
_Receiver,
222+
_Env2>;
223+
224+
using __mk_secondary_env_t =
225+
STDEXEC::__mk_secondary_env_t<set_value_t, set_error_t, set_stopped_t>;
226+
227+
template <class _CvInitialSender, class _Receiver>
228+
using __env2_t = __call_result_t<__mk_secondary_env_t, _CvInitialSender, env_of_t<_Receiver>>;
216229

217230
template <class _CvInitialSender, class _CvFinalSender, class _Receiver>
218-
struct __opstate : __final_opstate_t<_CvInitialSender, _CvFinalSender, _Receiver>
231+
struct __opstate
232+
: __final_opstate_t<_CvInitialSender,
233+
_CvFinalSender,
234+
_Receiver,
235+
__env2_t<_CvInitialSender, _Receiver>>
219236
{
220-
using __base_t = __final_opstate_t<_CvInitialSender, _CvFinalSender, _Receiver>;
237+
using __env2_t = __final::__env2_t<_CvInitialSender, _Receiver>;
238+
using __base_t = __final_opstate_t<_CvInitialSender, _CvFinalSender, _Receiver, __env2_t>;
221239
using __initial_results_t = __base_t::__results_t;
222240

223241
constexpr explicit __opstate(_CvInitialSender&& __initial,
224242
_CvFinalSender&& __final,
225243
_Receiver __rcvr)
226244
: __base_t(&__cleanup_initial_opstate,
227245
static_cast<_CvFinalSender&&>(__final),
228-
static_cast<_Receiver&&>(__rcvr))
246+
static_cast<_Receiver&&>(__rcvr),
247+
__mk_secondary_env_t{}(__initial, STDEXEC::get_env(__rcvr)))
229248
{
230249
__initial_opstate_.__emplace_from(STDEXEC::connect,
231250
static_cast<_CvInitialSender&&>(__initial),
@@ -239,7 +258,7 @@ namespace STDEXEC
239258

240259
private:
241260
using __initial_receiver_t =
242-
__initial_receiver<_CvFinalSender, __initial_results_t, _Receiver>;
261+
__initial_receiver<_CvFinalSender, __initial_results_t, _Receiver, __env2_t>;
243262
using __initial_opstate_t = connect_result_t<_CvInitialSender, __initial_receiver_t>;
244263

245264
static constexpr void __cleanup_initial_opstate(__base_t* __base) noexcept
@@ -251,7 +270,7 @@ namespace STDEXEC
251270
__optional<__initial_opstate_t> __initial_opstate_{};
252271
};
253272

254-
template <class _CvFinalSender, class _ResultType, class _Receiver>
273+
template <class _CvFinalSender, class _ResultType, class _Receiver, class _Env2>
255274
struct __initial_receiver
256275
{
257276
using receiver_concept = receiver_t;
@@ -281,7 +300,7 @@ namespace STDEXEC
281300
return STDEXEC::get_env(__opstate_->__rcvr_);
282301
}
283302

284-
__final_opstate<_CvFinalSender, _ResultType, _Receiver>* __opstate_;
303+
__final_opstate<_CvFinalSender, _ResultType, _Receiver, _Env2>* __opstate_;
285304
};
286305

287306
template <class _CvInitialSender, class _CvFinalSender, class... _Env>

include/stdexec/__detail/__let.hpp

Lines changed: 21 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -64,37 +64,11 @@ namespace STDEXEC
6464
using __on_not_callable =
6565
__mbind_front_q<__callable_error_t, decltype(__let_from_set<_SetTag>)>;
6666

67-
// This environment is part of the receiver used to connect the secondary sender.
68-
template <class _SetTag, class _Attrs, class... _Env>
69-
constexpr auto __mk_env2(_Attrs const & __attrs, _Env const &... __env) noexcept
70-
{
71-
if constexpr (__callable<get_completion_scheduler_t<_SetTag>,
72-
_Attrs const &,
73-
__fwd_env_t<_Env const &>...>)
74-
{
75-
return __mk_sch_env(get_completion_scheduler<_SetTag>(__attrs, __fwd_env(__env)...),
76-
__fwd_env(__env)...);
77-
}
78-
else if constexpr (__callable<get_completion_domain_t<_SetTag>,
79-
_Attrs const &,
80-
__fwd_env_t<_Env const &>...>)
81-
{
82-
using __domain_t = __call_result_t<get_completion_domain_t<_SetTag>,
83-
_Attrs const &,
84-
__fwd_env_t<_Env const &>...>;
85-
return prop{get_domain, __domain_t{}};
86-
}
87-
else
88-
{
89-
return env{};
90-
}
91-
}
67+
template <class _SetTag, class _Sender, class... _Env>
68+
using __env2_t = __call_result_t<__mk_secondary_env_t<_SetTag>, _Sender, _Env const &...>;
9269

93-
template <class _SetTag, class _Attrs, class... _Env>
94-
using __env2_t = decltype(__let::__mk_env2<_SetTag>(__declval<_Attrs>(), __declval<_Env>()...));
95-
96-
template <class _SetTag, class _Attrs, class _Env>
97-
using __result_env_t = __join_env_t<__env2_t<_SetTag, _Attrs, _Env>, _Env>;
70+
template <class _SetTag, class _Sender, class _Env>
71+
using __result_env_t = __join_env_t<__env2_t<_SetTag, _Sender, _Env>, _Env>;
9872

9973
template <class _Receiver, class _Env2>
10074
struct __rcvr_env
@@ -209,10 +183,9 @@ namespace STDEXEC
209183
using __completions_t = __gather_completion_signatures_t<
210184
__completion_signatures_of_t<_CvSender, _Env...>,
211185
__t<_LetTag>,
212-
__transform_signal_fn<
213-
__t<_LetTag>,
214-
_Fun,
215-
__result_env_t<__t<_LetTag>, env_of_t<_CvSender>, _Env>...>::template __f,
186+
__transform_signal_fn<__t<_LetTag>,
187+
_Fun,
188+
__result_env_t<__t<_LetTag>, _CvSender, _Env>...>::template __f,
216189
__cmplsigs::__default_completion,
217190
__mtry_q<__concat_completion_signatures_t>::__f>;
218191

@@ -243,7 +216,7 @@ namespace STDEXEC
243216
using __result_domain_t = __gather_completions_t<
244217
_SetTag,
245218
__completion_signatures_of_t<_Child, _Env>,
246-
__result_sender_fn<_SetTag, _Fun, __result_env_t<_SetTag, env_of_t<_Child>, _Env>>,
219+
__result_sender_fn<_SetTag, _Fun, __result_env_t<_SetTag, _Child, _Env>>,
247220
__try_common_domain_fn<_SetTag, _Env>>;
248221

249222
//! Metafunction creating the operation state needed to connect the result of calling
@@ -278,7 +251,7 @@ namespace STDEXEC
278251
using __has_nothrow_completions_t = __gather_completions_t<
279252
completion_signatures_of_t<_Child, _Env>,
280253
_SetTag,
281-
__has_nothrow_completions_fn<_Fn, __result_env_t<_SetTag, env_of_t<_Child>, _Env>>,
254+
__has_nothrow_completions_fn<_Fn, __result_env_t<_SetTag, _Child, _Env>>,
282255
__qq<__mand_t>>;
283256

284257
//! The core of the operation state for `let_*`.
@@ -289,15 +262,15 @@ namespace STDEXEC
289262
using __env2_t = _Env2;
290263
using __second_rcvr_t = __rcvr_env<_Receiver, _Env2>;
291264

292-
template <class _Attrs>
265+
template <class _Sender>
293266
constexpr explicit __opstate_base(_SetTag,
294-
_Attrs const & __attrs,
295-
_Fun __fn,
296-
_Receiver&& __rcvr) noexcept
267+
_Sender const & __sndr,
268+
_Fun __fn,
269+
_Receiver&& __rcvr) noexcept
297270
: __rcvr_(static_cast<_Receiver&&>(__rcvr))
298271
, __fn_(STDEXEC::__allocator_aware_forward(static_cast<_Fun&&>(__fn), __rcvr_))
299272
// TODO(ericniebler): this needs a fallback:
300-
, __env2_(__let::__mk_env2<_SetTag>(__attrs, STDEXEC::get_env(__rcvr_)))
273+
, __env2_(__mk_secondary_env_t<_SetTag>()(__sndr, STDEXEC::get_env(__rcvr_)))
301274
{}
302275

303276
constexpr virtual void __start_next() = 0;
@@ -400,7 +373,7 @@ namespace STDEXEC
400373
: __opstate_base<_SetTag,
401374
_Fun,
402375
_Receiver,
403-
__let::__env2_t<_SetTag, env_of_t<_Child>, env_of_t<_Receiver>>,
376+
__let::__env2_t<_SetTag, _Child, env_of_t<_Receiver>>,
404377
_Tuples...>
405378
{
406379
using __env2_t = __opstate::__opstate_base::__env2_t;
@@ -415,7 +388,7 @@ namespace STDEXEC
415388
noexcept(__nothrow_connectable<_Child, __first_rcvr_t>
416389
&& __nothrow_move_constructible<_Fun>)
417390
: __opstate::__opstate_base(_SetTag(),
418-
STDEXEC::get_env(__child),
391+
__child,
419392
static_cast<_Fun&&>(__fn),
420393
static_cast<_Receiver&&>(__rcvr))
421394
{
@@ -512,16 +485,16 @@ namespace STDEXEC
512485
using __f = decltype(__impl<_Ts...>());
513486
};
514487

515-
template <class _SetTag, class _Fn, class _Attrs, class... _Env>
488+
template <class _SetTag, class _Fn, class _Sender, class... _Env>
516489
struct __domain_transform_fn
517490
{
518491
using __result_sender_fn =
519-
__let::__result_sender_fn<_SetTag, _Fn, __result_env_t<_SetTag, _Attrs, _Env>...>;
492+
__let::__result_sender_fn<_SetTag, _Fn, __result_env_t<_SetTag, _Sender, _Env>...>;
520493

521494
template <class... _As>
522495
using __f = __completion_domain_of_t<_SetTag,
523496
__mcall<__result_sender_fn, _As...>,
524-
__result_env_t<_SetTag, _Attrs, _Env>...>;
497+
__result_env_t<_SetTag, _Sender, _Env>...>;
525498
};
526499

527500
//! @tparam _LetTag The tag type for the let_ operation.
@@ -534,8 +507,7 @@ namespace STDEXEC
534507
{
535508
if constexpr (sender_in<_Sndr, _Env...>)
536509
{
537-
using __domain_transform_fn =
538-
__let::__domain_transform_fn<_SetTag, _Fn, env_of_t<_Sndr>, _Env...>;
510+
using __domain_transform_fn = __let::__domain_transform_fn<_SetTag, _Fn, _Sndr, _Env...>;
539511
return __minvoke_or_q<__gather_completions_t,
540512
indeterminate_domain<>,
541513
__t<_LetTag>,
@@ -606,7 +578,7 @@ namespace STDEXEC
606578
using __transform_fn =
607579
__result_completion_behavior_fn<__set_tag_t,
608580
_Fn,
609-
__result_env_t<__set_tag_t, env_of_t<_Sndr>, _Env>...>;
581+
__result_env_t<__set_tag_t, _Sndr, _Env>...>;
610582
using __completions_t = __completion_signatures_of_t<_Sndr, __fwd_env_t<_Env>...>;
611583

612584
constexpr auto __pred_behavior =

0 commit comments

Comments
 (0)