| 149 | |
| 150 | template <class _Child, class _Receiver> |
| 151 | struct __opstate final : __opstate_base<_Receiver> |
| 152 | { |
| 153 | using __receiver_t = __receiver<_Receiver>; |
| 154 | using __bouncy_sndr_t = |
| 155 | __result_of<exec::sequence, schedule_result_t<trampoline_scheduler>, _Child &>; |
| 156 | using __child_op_t = STDEXEC::connect_result_t<__bouncy_sndr_t, __receiver_t>; |
| 157 | |
| 158 | static constexpr bool __nothrow_connect = |
| 159 | __nothrow_invocable<STDEXEC::schedule_t, trampoline_scheduler> |
| 160 | && __nothrow_invocable<sequence_t, schedule_result_t<trampoline_scheduler>, _Child &> |
| 161 | && __nothrow_connectable<__bouncy_sndr_t, __receiver_t>; |
| 162 | |
| 163 | constexpr explicit __opstate(_Child __child, _Receiver __rcvr) |
| 164 | noexcept(__nothrow_move_constructible<_Child> && __nothrow_connect) |
| 165 | : __opstate_base<_Receiver>(std::move(__rcvr)) |
| 166 | , __child_(std::move(__child)) |
| 167 | { |
| 168 | __connect(); |
| 169 | } |
| 170 | |
| 171 | constexpr void start() noexcept |
| 172 | { |
| 173 | STDEXEC::start(*__child_op_); |
| 174 | } |
| 175 | |
| 176 | constexpr auto __connect() noexcept(__nothrow_connect) -> __child_op_t & |
| 177 | { |
| 178 | return __child_op_.__emplace_from(STDEXEC::connect, |
| 179 | exec::sequence(STDEXEC::schedule(trampoline_scheduler{}), |
| 180 | __child_), |
| 181 | __receiver_t{this}); |
| 182 | } |
| 183 | |
| 184 | constexpr void __cleanup() noexcept final |
| 185 | { |
| 186 | __child_op_.reset(); |
| 187 | } |
| 188 | |
| 189 | constexpr void __repeat() noexcept final |
| 190 | { |
| 191 | STDEXEC_TRY |
| 192 | { |
| 193 | STDEXEC::start(__connect()); |
| 194 | } |
| 195 | STDEXEC_CATCH_ALL |
| 196 | { |
| 197 | if constexpr (!__nothrow_connect) |
| 198 | { |
| 199 | STDEXEC::set_error(static_cast<_Receiver &&>(this->__rcvr_), std::current_exception()); |
| 200 | } |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | _Child __child_; |
| 205 | STDEXEC::__optional<__child_op_t> __child_op_; |
no test coverage detected