@@ -210,33 +210,33 @@ namespace STDEXEC
210210 struct __opstate
211211 {
212212 constexpr explicit __opstate (_Awaitable&& __awaitable, _Receiver&& __rcvr)
213- noexcept (__is_nothrow )
213+ noexcept (__nothrow_move_constructible<_Awaitable> )
214214 : __rcvr_(static_cast <_Receiver&&>(__rcvr))
215- , __coro_(__co_impl(*this ))
216- , __awaitable1_(static_cast <_Awaitable&&>(__awaitable))
217- , __awaitable2_(
218- __get_awaitable (static_cast <_Awaitable&&>(__awaitable1_), __coro_.promise()))
219- , __awaiter_(__get_awaiter(static_cast <__awaitable_t &&>(__awaitable2_)))
215+ , __source_awaitable_(static_cast <_Awaitable&&>(__awaitable))
220216 {}
221217
222218 void start () & noexcept
223219 {
220+ auto __coro = __co_impl (*this );
221+
224222 STDEXEC_TRY
225223 {
226- if (!__awaiter_.await_ready ())
224+ __awaiter_.emplace (__source_awaitable_, __coro);
225+
226+ if (!__awaiter_->await_ready ())
227227 {
228- using __suspend_result_t = decltype (__awaiter_. await_suspend (__coro_ ));
228+ using __suspend_result_t = decltype (__awaiter_-> await_suspend (__coro ));
229229
230230 // suspended
231231 if constexpr (std::is_void_v<__suspend_result_t >)
232232 {
233233 // void-returning await_suspend means "always suspend"
234- __awaiter_. await_suspend (__coro_ );
234+ __awaiter_-> await_suspend (__coro );
235235 return ;
236236 }
237237 else if constexpr (std::same_as<bool , __suspend_result_t >)
238238 {
239- if (__awaiter_. await_suspend (__coro_ ))
239+ if (__awaiter_-> await_suspend (__coro ))
240240 {
241241 // returning true from a bool-returning await_suspend means suspend
242242 return ;
@@ -249,7 +249,7 @@ namespace STDEXEC
249249 else
250250 {
251251 static_assert (__std::convertible_to<__suspend_result_t , __std::coroutine_handle<>>);
252- auto __resume_target = __awaiter_. await_suspend (__coro_ );
252+ auto __resume_target = __awaiter_-> await_suspend (__coro );
253253 STDEXEC_TRY
254254 {
255255 __resume_target.resume ();
@@ -270,8 +270,11 @@ namespace STDEXEC
270270 }
271271 STDEXEC_CATCH_ALL
272272 {
273- if constexpr (!noexcept (__awaiter_.await_ready ())
274- || !noexcept (__awaiter_.await_suspend (__coro_)))
273+ if constexpr (!__nothrow_constructible_from<__awaitable_state,
274+ _Awaitable&,
275+ __std::coroutine_handle<__promise_t >>
276+ || !noexcept (__awaiter_->await_ready ())
277+ || !noexcept (__awaiter_->await_suspend (__coro)))
275278 {
276279 STDEXEC::set_error (static_cast <_Receiver&&>(__rcvr_), std::current_exception ());
277280 }
@@ -286,10 +289,6 @@ namespace STDEXEC
286289 friend __promise_t ;
287290 friend __final_awaiter;
288291
289- static constexpr bool __is_nothrow = __nothrow_move_constructible<_Awaitable>
290- && __noexcept_of<__get_awaitable, _Awaitable, __promise_t &>
291- && __noexcept_of<__get_awaiter, __awaitable_t >;
292-
293292 static auto __co_impl (__opstate&) noexcept -> __std::coroutine_handle<__promise_t>
294293 {
295294 co_return ;
@@ -299,19 +298,19 @@ namespace STDEXEC
299298 {
300299 STDEXEC_TRY
301300 {
302- if constexpr (std::is_void_v<decltype (__awaiter_. await_resume ())>)
301+ if constexpr (std::is_void_v<decltype (__awaiter_-> await_resume ())>)
303302 {
304- __awaiter_. await_resume ();
303+ __awaiter_-> await_resume ();
305304 STDEXEC::set_value (static_cast <_Receiver&&>(__rcvr_));
306305 }
307306 else
308307 {
309- STDEXEC::set_value (static_cast <_Receiver&&>(__rcvr_), __awaiter_. await_resume ());
308+ STDEXEC::set_value (static_cast <_Receiver&&>(__rcvr_), __awaiter_-> await_resume ());
310309 }
311310 }
312311 STDEXEC_CATCH_ALL
313312 {
314- if constexpr (!noexcept (__awaiter_. await_resume ()))
313+ if constexpr (!noexcept (__awaiter_-> await_resume ()))
315314 {
316315 STDEXEC::set_error (static_cast <_Receiver&&>(__rcvr_), std::current_exception ());
317316 }
@@ -323,12 +322,45 @@ namespace STDEXEC
323322 STDEXEC::set_stopped (static_cast <_Receiver&&>(__rcvr_));
324323 }
325324
325+ struct __awaitable_state
326+ {
327+ explicit __awaitable_state (_Awaitable& __source,
328+ __std::coroutine_handle<__promise_t > __coro)
329+ noexcept (__is_nothrow)
330+ : __awaitable_(__get_awaitable(static_cast <_Awaitable&&>(__source), __coro.promise()))
331+ , __awaiter_(__get_awaiter(static_cast <__awaitable_t &&>(__awaitable_)))
332+ {}
333+
334+ constexpr auto await_ready () noexcept (noexcept (__awaiter_.await_ready())) -> bool
335+ {
336+ return __awaiter_.await_ready ();
337+ }
338+
339+ template <class _P >
340+ constexpr auto await_suspend (__std::coroutine_handle<_P> __h)
341+ noexcept (noexcept (__awaiter_.await_suspend(__h)))
342+ {
343+ return __awaiter_.await_suspend (__h);
344+ }
345+
346+ constexpr decltype (auto ) await_resume() noexcept (noexcept (__awaiter_.await_resume()))
347+ {
348+ return __awaiter_.await_resume ();
349+ }
350+
351+ private:
352+ static constexpr bool __is_nothrow =
353+ __noexcept_of<__get_awaitable, _Awaitable, __promise_t &>
354+ && __noexcept_of<__get_awaiter, __awaitable_t >;
355+
356+ __awaitable_t __awaitable_;
357+ __awaiter_t __awaiter_;
358+ };
359+
326360 alignas (__storage_align) std::byte __storage_[__storage_size];
327- _Receiver __rcvr_;
328- __std::coroutine_handle<__promise_t > __coro_;
329- _Awaitable __awaitable1_;
330- __awaitable_t __awaitable2_;
331- __awaiter_t __awaiter_;
361+ _Receiver __rcvr_;
362+ _Awaitable __source_awaitable_;
363+ __optional<__awaitable_state> __awaiter_;
332364 };
333365 } // namespace __connect_await
334366
0 commit comments