@@ -45,8 +45,7 @@ namespace experimental::execution
4545 using __any_scheduler_completions =
4646 completion_signatures<set_value_t (), set_error_t (std::exception_ptr), set_stopped_t ()>;
4747
48- using __any_scheduler =
49- any_receiver_ref<__any_scheduler_completions>::any_sender<>::any_scheduler<>;
48+ using __any_scheduler = any_scheduler<any_sender<any_receiver<__any_scheduler_completions>>>;
5049
5150 static_assert (scheduler<__any_scheduler>);
5251
@@ -59,17 +58,17 @@ namespace experimental::execution
5958 };
6059
6160 template <class _Ty >
62- concept __indirect_scheduler_provider = requires (_Ty const & t) {
63- { get_env (t) } -> __scheduler_provider ;
61+ concept __indirect_start_scheduler_provider = requires (_Ty const & t) {
62+ { get_start_scheduler ( get_env (t)) } -> scheduler ;
6463 };
6564
6665 template <class _ParentPromise >
67- constexpr auto __check_parent_promise_has_scheduler () noexcept -> bool
66+ constexpr auto __parent_promise_has_start_scheduler () noexcept -> bool
6867 {
69- static_assert (__indirect_scheduler_provider <_ParentPromise>,
68+ static_assert (__indirect_start_scheduler_provider <_ParentPromise>,
7069 " exec::task<T> cannot be co_await-ed in a coroutine that "
71- " does not have an associated scheduler." );
72- return __indirect_scheduler_provider <_ParentPromise>;
70+ " does not have an associated start scheduler." );
71+ return __indirect_start_scheduler_provider <_ParentPromise>;
7372 }
7473
7574 template <class _ParentPromise >
@@ -84,41 +83,59 @@ namespace experimental::execution
8483 __sticky
8584 };
8685
86+ template <__scheduler_affinity _SchedulerAffinity>
87+ struct __optional_scheduler_storage
88+ {
89+ __optional_scheduler_storage () = default ;
90+ constexpr explicit __optional_scheduler_storage (__ignore) noexcept {}
91+ };
92+
93+ template <>
94+ struct __optional_scheduler_storage <__scheduler_affinity::__sticky>
95+ {
96+ __optional_scheduler_storage () = default ;
97+
98+ template <scheduler _Scheduler>
99+ constexpr explicit __optional_scheduler_storage (_Scheduler __sched) noexcept
100+ : __scheduler_(__sched)
101+ {}
102+
103+ __any_scheduler __scheduler_{STDEXEC::inline_scheduler{}};
104+ };
105+
87106 template <__scheduler_affinity _SchedulerAffinity = __scheduler_affinity::__sticky>
88- class __default_task_context_impl
107+ class __default_task_context_impl : private __optional_scheduler_storage <_SchedulerAffinity>
89108 {
90109 template <class _ParentPromise >
91110 friend struct __default_awaiter_context ;
92111
93- static constexpr bool __with_scheduler = _SchedulerAffinity == __scheduler_affinity::__sticky;
112+ static constexpr bool __with_affinity = _SchedulerAffinity == __scheduler_affinity::__sticky;
94113
95- STDEXEC_ATTRIBUTE (no_unique_address)
96- __if_c<__with_scheduler, __any_scheduler, __ignore> __scheduler_{STDEXEC::inline_scheduler{}};
97- inplace_stop_token __stop_token_;
114+ inplace_stop_token __stop_token_;
98115
99116 public:
100117 template <class _ParentPromise >
101118 constexpr explicit __default_task_context_impl (_ParentPromise& __parent) noexcept
102119 {
103- if constexpr (_SchedulerAffinity == __scheduler_affinity::__sticky )
120+ if constexpr (__with_affinity && __parent_promise_has_start_scheduler<_ParentPromise>() )
104121 {
105- if constexpr (__check_parent_promise_has_scheduler<_ParentPromise>())
106- {
107- __scheduler_ = get_scheduler (get_env (__parent));
108- }
122+ // get_start_scheduler is used here to get the parent's "current" scheduler,
123+ // which is the one on which this task has been started (i.e., co_await-ed).
124+ auto __parent_sched = get_start_scheduler (get_env (__parent));
125+ this -> __scheduler_ = __parent_sched;
109126 }
110127 }
111128
112129 template <scheduler _Scheduler>
113- constexpr explicit __default_task_context_impl (_Scheduler&& __scheduler)
114- : __scheduler_ {static_cast <_Scheduler&&>(__scheduler )}
130+ constexpr explicit __default_task_context_impl (_Scheduler&& __sched) noexcept
131+ : __optional_scheduler_storage<_SchedulerAffinity> {static_cast <_Scheduler&&>(__sched )}
115132 {}
116133
117134 [[nodiscard]]
118- constexpr auto query (get_scheduler_t ) const noexcept -> __any_scheduler const &
119- requires(__with_scheduler )
135+ constexpr auto query (get_start_scheduler_t ) const noexcept -> __any_scheduler const &
136+ requires(__with_affinity )
120137 {
121- return __scheduler_;
138+ return this -> __scheduler_ ;
122139 }
123140
124141 [[nodiscard]]
@@ -130,7 +147,7 @@ namespace experimental::execution
130147 [[nodiscard]]
131148 constexpr auto query (get_completion_behavior_t <set_value_t >) const noexcept
132149 {
133- if constexpr (__with_scheduler )
150+ if constexpr (__with_affinity )
134151 {
135152 return completion_behavior::asynchronous_affine | completion_behavior::inline_completion;
136153 }
@@ -148,24 +165,24 @@ namespace experimental::execution
148165
149166 template <scheduler _Scheduler>
150167 constexpr void set_scheduler (_Scheduler&& __sched)
151- requires(__with_scheduler )
168+ requires(__with_affinity )
152169 {
153- __scheduler_ = static_cast <_Scheduler&&>(__sched);
170+ this -> __scheduler_ = static_cast <_Scheduler&&>(__sched);
154171 }
155172
156173 template <class _ThisPromise >
157174 using promise_context_t = __default_task_context_impl;
158175
159176 template <class _ThisPromise , class _ParentPromise = void >
160- requires (!__with_scheduler ) || __indirect_scheduler_provider <_ParentPromise>
177+ requires (!__with_affinity ) || __indirect_start_scheduler_provider <_ParentPromise>
161178 using awaiter_context_t = __default_awaiter_context<_ParentPromise>;
162179 };
163180
164181 template <class _Ty >
165182 using default_task_context = __default_task_context_impl<__scheduler_affinity::__sticky>;
166183
167184 template <class _Ty >
168- using __raw_task_context = __default_task_context_impl<__scheduler_affinity::__none>;
185+ using inline_task_context = __default_task_context_impl<__scheduler_affinity::__none>;
169186
170187 // This is the context associated with basic_task's awaiter. By default
171188 // it does nothing.
@@ -387,7 +404,7 @@ namespace experimental::execution
387404 if (!std::exchange (__p.__rescheduled_ , true ))
388405 {
389406 // Create a cleanup action that transitions back onto the current scheduler:
390- auto __sched = get_scheduler (*__p.__context_ );
407+ auto __sched = get_start_scheduler (*__p.__context_ );
391408 auto __guard = at_coroutine_exit (__compose (unstoppable, STDEXEC::schedule),
392409 std::move (__sched));
393410 // Insert the cleanup action into the head of the continuation chain by
@@ -483,7 +500,7 @@ namespace experimental::execution
483500
484501 private:
485502 using __scheduler_t =
486- __call_result_or_t <get_scheduler_t , STDEXEC::inline_scheduler, _Context>;
503+ __call_result_or_t <get_start_scheduler_t , STDEXEC::inline_scheduler, _Context>;
487504
488505 struct __final_awaitable
489506 {
@@ -541,7 +558,7 @@ namespace experimental::execution
541558
542559#ifndef __clang_analyzer__
543560 template <sender _CvSender>
544- requires __scheduler_provider <_Context>
561+ requires __start_scheduler_provider <_Context>
545562 auto await_transform (_CvSender&& __sndr) noexcept -> decltype(auto )
546563 {
547564 if constexpr (__completes_where_it_starts<set_value_t ,
@@ -553,13 +570,13 @@ namespace experimental::execution
553570 else
554571 {
555572 return STDEXEC::as_awaitable (continues_on (static_cast <_CvSender&&>(__sndr),
556- get_scheduler (*__context_)),
573+ get_start_scheduler (*__context_)),
557574 *this );
558575 }
559576 }
560577
561578 template <class _Scheduler >
562- requires __scheduler_provider <_Context>
579+ requires __start_scheduler_provider <_Context>
563580 auto await_transform (__reschedule_coroutine_on_t ::__wrapper<_Scheduler> __box) noexcept
564581 -> decltype(auto )
565582 {
@@ -592,6 +609,11 @@ namespace experimental::execution
592609 template <class _ParentPromise >
593610 struct __task_awaiter
594611 {
612+ constexpr __task_awaiter (__std::coroutine_handle<__promise> __coro) noexcept
613+ : __coro_(__coro)
614+ {}
615+ STDEXEC_IMMOVABLE (__task_awaiter);
616+
595617 constexpr ~__task_awaiter ()
596618 {
597619 if (__coro_)
@@ -631,7 +653,7 @@ namespace experimental::execution
631653 return std::move (__var::__get<0 >(__coro_.promise ().__data_ ));
632654 }
633655
634- __std::coroutine_handle<__promise> __coro_;
656+ __std::coroutine_handle<__promise> __coro_{} ;
635657 __optional<awaiter_context_t <__promise, _ParentPromise>> __context_{};
636658 };
637659
@@ -640,7 +662,7 @@ namespace experimental::execution
640662 : __coro_ (__coro)
641663 {}
642664
643- __std::coroutine_handle<promise_type> __coro_;
665+ __std::coroutine_handle<promise_type> __coro_{} ;
644666 };
645667 } // namespace __task
646668
0 commit comments