| 125 | |
| 126 | template <class... _Ts> |
| 127 | class [[nodiscard]] __task |
| 128 | { |
| 129 | struct __promise; |
| 130 | public: |
| 131 | using promise_type = __promise; |
| 132 | |
| 133 | explicit(!STDEXEC_EDG()) __task(__std::coroutine_handle<__promise> __coro) noexcept |
| 134 | : __coro_(__coro) |
| 135 | {} |
| 136 | |
| 137 | __task(__task&& __that) noexcept |
| 138 | : __coro_(std::exchange(__that.__coro_, {})) |
| 139 | {} |
| 140 | |
| 141 | ~__task() |
| 142 | { |
| 143 | if (__coro_) |
| 144 | STDEXEC::__coroutine_destroy_nothrow(__coro_); |
| 145 | } |
| 146 | |
| 147 | [[nodiscard]] |
| 148 | static constexpr auto await_ready() noexcept -> bool |
| 149 | { |
| 150 | return false; |
| 151 | } |
| 152 | |
| 153 | //! \brief Splice the cleanup action into the chain of continuations. |
| 154 | //! \param __parent The coroutine that is registering an action to be performed at |
| 155 | //! coroutine exit; i.e., the coroutine that is co_await-ing the result of calling |
| 156 | //! at_coroutine_exit. |
| 157 | template <__has_continuation _Promise> |
| 158 | auto await_suspend(__std::coroutine_handle<_Promise> __parent) -> bool |
| 159 | { |
| 160 | // Set the cleanup task's scheduler to the parent coroutine's scheduler. |
| 161 | __coro_.promise().__scheduler_ = get_start_scheduler(get_env(__parent.promise())); |
| 162 | // This causes the parent to be resumed after the cleanup action is performed. |
| 163 | __coro_.promise().set_continuation(__parent.promise().continuation()); |
| 164 | // This causes the parent to invoke the cleanup action when it performs the final |
| 165 | // suspend. Also, the parent is now responsible for destroying the cleanup |
| 166 | // coroutine. |
| 167 | __parent.promise().set_continuation(__coro_); |
| 168 | return false; // i.e., do not suspend, call await_resume immediately |
| 169 | } |
| 170 | |
| 171 | auto await_resume() noexcept -> std::tuple<_Ts&...> |
| 172 | { |
| 173 | // Release the cleanup coroutine. It is now responsible for destroying itself in |
| 174 | // its final suspend. |
| 175 | return std::exchange(__coro_, {}).promise().__args_; |
| 176 | } |
| 177 | |
| 178 | private: |
| 179 | struct __final_awaiter |
| 180 | { |
| 181 | static constexpr auto await_ready() noexcept -> bool |
| 182 | { |
| 183 | return false; |
| 184 | } |