File indexing completed on 2025-12-16 09:59:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #ifndef BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_BEGIN
0032 #error This header must only be included by outcome/coroutine_support.hpp or outcome/experimental/coroutine_support.hpp
0033 #endif
0034
0035 #ifndef BOOST_OUTCOME_DETAIL_COROUTINE_SUPPORT_HPP
0036 #define BOOST_OUTCOME_DETAIL_COROUTINE_SUPPORT_HPP
0037
0038 #include <atomic>
0039 #include <exception>
0040
0041 #ifndef BOOST_OUTCOME_COROUTINE_HEADER_TYPE
0042 #if __has_include(<coroutine>)
0043 #define BOOST_OUTCOME_COROUTINE_HEADER_TYPE 1
0044 #elif __has_include(<experimental/coroutine>)
0045 #define BOOST_OUTCOME_COROUTINE_HEADER_TYPE 2
0046 #else
0047 #define BOOST_OUTCOME_COROUTINE_HEADER_TYPE 0
0048 #endif
0049 #endif
0050
0051 #if BOOST_OUTCOME_COROUTINE_HEADER_TYPE && (__cpp_impl_coroutine || (defined(_MSC_VER) && __cpp_coroutines))
0052 #ifndef BOOST_OUTCOME_HAVE_NOOP_COROUTINE
0053 #if defined(__has_builtin)
0054 #if __has_builtin(__builtin_coro_noop) || (!defined(__clang__) && __GNUC__ >= 10)
0055 #define BOOST_OUTCOME_HAVE_NOOP_COROUTINE 1
0056 #endif
0057 #endif
0058 #endif
0059 #ifndef BOOST_OUTCOME_HAVE_NOOP_COROUTINE
0060 #if _MSC_VER >= 1928 || (!defined(__clang__) && __GNUC__ >= 10)
0061 #define BOOST_OUTCOME_HAVE_NOOP_COROUTINE 1
0062 #else
0063 #define BOOST_OUTCOME_HAVE_NOOP_COROUTINE 0
0064 #endif
0065 #endif
0066 #if BOOST_OUTCOME_COROUTINE_HEADER_TYPE == 1
0067 #include <coroutine>
0068 BOOST_OUTCOME_V2_NAMESPACE_BEGIN
0069 namespace awaitables
0070 {
0071 template <class Promise = void> using coroutine_handle = std::coroutine_handle<Promise>;
0072 template <class... Args> using coroutine_traits = std::coroutine_traits<Args...>;
0073 using std::suspend_always;
0074 using std::suspend_never;
0075 #if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
0076 using std::noop_coroutine;
0077 #endif
0078 }
0079 BOOST_OUTCOME_V2_NAMESPACE_END
0080 #define BOOST_OUTCOME_FOUND_COROUTINE_HEADER 1
0081 #elif BOOST_OUTCOME_COROUTINE_HEADER_TYPE == 2
0082 #include <experimental/coroutine>
0083 BOOST_OUTCOME_V2_NAMESPACE_BEGIN
0084 namespace awaitables
0085 {
0086 template <class Promise = void> using coroutine_handle = std::experimental::coroutine_handle<Promise>;
0087 template <class... Args> using coroutine_traits = std::experimental::coroutine_traits<Args...>;
0088 using std::experimental::suspend_always;
0089 using std::experimental::suspend_never;
0090 #if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
0091 using std::experimental::noop_coroutine;
0092 #endif
0093 }
0094 BOOST_OUTCOME_V2_NAMESPACE_END
0095 #define BOOST_OUTCOME_FOUND_COROUTINE_HEADER 1
0096 #endif
0097 #endif
0098
0099 #ifndef BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER
0100
0101
0102 #define BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(...)
0103 #endif
0104
0105 BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
0106 namespace awaitables
0107 {
0108 namespace detail
0109 {
0110 struct error_type_not_found
0111 {
0112 };
0113 struct exception_type_not_found
0114 {
0115 };
0116 template <class T> struct type_found
0117 {
0118 using type = T;
0119 };
0120 template <class T, class U = typename T::error_type> constexpr inline type_found<U> extract_error_type(int )
0121 {
0122 return {};
0123 }
0124 template <class T> constexpr inline type_found<error_type_not_found> extract_error_type(...)
0125 {
0126 return {};
0127 }
0128 template <class T, class U = typename T::exception_type> constexpr inline type_found<U> extract_exception_type(int )
0129 {
0130 return {};
0131 }
0132 template <class T> constexpr inline type_found<exception_type_not_found> extract_exception_type(...)
0133 {
0134 return {};
0135 }
0136
0137 BOOST_OUTCOME_TEMPLATE(class T, class U)
0138 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(BOOST_OUTCOME_V2_NAMESPACE::detail::is_constructible<U, T>))
0139 inline bool try_set_error(T &&e, U *result)
0140 {
0141 new(result) U(static_cast<T &&>(e));
0142 return true;
0143 }
0144 template <class T> inline bool try_set_error(T && , ...)
0145 {
0146 return false;
0147 }
0148 BOOST_OUTCOME_TEMPLATE(class T, class U)
0149 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(BOOST_OUTCOME_V2_NAMESPACE::detail::is_constructible<U, T>))
0150 inline void set_or_rethrow(T &e, U *result)
0151 {
0152 new(result) U(e);
0153 }
0154 template <class T> inline void set_or_rethrow(T &e, ...)
0155 {
0156 rethrow_exception(e);
0157 }
0158 template <class T> class fake_atomic
0159 {
0160 T _v;
0161
0162 public:
0163 constexpr fake_atomic(T v)
0164 : _v(v)
0165 {
0166 }
0167 T load(std::memory_order ) { return _v; }
0168 void store(T v, std::memory_order ) { _v = v; }
0169 bool compare_exchange_strong(T &expected, T v, std::memory_order , std::memory_order )
0170 {
0171 if(_v == expected)
0172 {
0173 _v = v;
0174 return true;
0175 }
0176 return false;
0177 }
0178 };
0179
0180 #ifdef BOOST_OUTCOME_FOUND_COROUTINE_HEADER
0181 template <class Awaitable, bool suspend_initial, bool use_atomic, bool is_void> struct outcome_promise_type
0182 {
0183 using container_type = typename Awaitable::container_type;
0184 using result_set_type = std::conditional_t<use_atomic, std::atomic<bool>, fake_atomic<bool>>;
0185 union
0186 {
0187 BOOST_OUTCOME_V2_NAMESPACE::detail::empty_type _default{};
0188 container_type result;
0189 };
0190 result_set_type result_set{false}, pending_first_resumption{is_initially_suspended};
0191 coroutine_handle<> continuation;
0192
0193 static constexpr bool is_initially_suspended = suspend_initial;
0194 static constexpr bool is_using_atomics = use_atomic;
0195
0196 outcome_promise_type() noexcept { BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(this << " promise constructed"); }
0197 outcome_promise_type(const outcome_promise_type &) = delete;
0198 outcome_promise_type(outcome_promise_type &&) = delete;
0199 outcome_promise_type &operator=(const outcome_promise_type &) = delete;
0200 outcome_promise_type &operator=(outcome_promise_type &&) = delete;
0201 ~outcome_promise_type()
0202 {
0203 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(this << " promise destructs");
0204 if(result_set.load(std::memory_order_acquire))
0205 {
0206 result.~container_type();
0207 }
0208 }
0209 auto get_return_object()
0210 {
0211 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(this << " promise returns awaitable");
0212 return Awaitable{*this};
0213 }
0214 void return_value(container_type &&value)
0215 {
0216 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(this << " promise returns value");
0217 BOOST_OUTCOME_ASSERT(!result_set.load(std::memory_order_acquire));
0218 if(result_set.load(std::memory_order_acquire))
0219 {
0220 result.~container_type();
0221 }
0222 new(&result) container_type(static_cast<container_type &&>(value));
0223 result_set.store(true, std::memory_order_release);
0224 }
0225 void return_value(const container_type &value)
0226 {
0227 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(this << " promise returns value");
0228 BOOST_OUTCOME_ASSERT(!result_set.load(std::memory_order_acquire));
0229 if(result_set.load(std::memory_order_acquire))
0230 {
0231 result.~container_type();
0232 }
0233 new(&result) container_type(value);
0234 result_set.store(true, std::memory_order_release);
0235 }
0236 void unhandled_exception()
0237 {
0238 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(this << " promise unhandled exception");
0239 BOOST_OUTCOME_ASSERT(!result_set.load(std::memory_order_acquire));
0240 if(result_set.load(std::memory_order_acquire))
0241 {
0242 result.~container_type();
0243 }
0244 #ifndef BOOST_NO_EXCEPTIONS
0245 auto e = std::current_exception();
0246 auto ec = detail::error_from_exception(static_cast<decltype(e) &&>(e), {});
0247
0248 if(!detail::error_is_set(ec) || !detail::try_set_error(static_cast<decltype(ec) &&>(ec), &result))
0249 {
0250 detail::set_or_rethrow(e, &result);
0251 }
0252 #else
0253 std::terminate();
0254 #endif
0255 result_set.store(true, std::memory_order_release);
0256 }
0257 auto initial_suspend() noexcept
0258 {
0259 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(this << " promise initial suspend = " << suspend_initial);
0260 struct awaiter
0261 {
0262 constexpr bool await_ready() noexcept { return !suspend_initial; }
0263 void await_resume() noexcept {}
0264 void await_suspend(coroutine_handle<> ) noexcept {}
0265 };
0266 return awaiter{};
0267 }
0268 auto final_suspend() noexcept
0269 {
0270 struct awaiter
0271 {
0272
0273
0274 constexpr bool await_ready() noexcept { return false; }
0275 void await_resume() noexcept {}
0276 #if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
0277 coroutine_handle<> await_suspend(coroutine_handle<outcome_promise_type> self) noexcept
0278 {
0279 if(self.promise().continuation)
0280 {
0281 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&self.promise() << " promise final suspend will resume coroutine " << self.promise().continuation.address());
0282 }
0283 else
0284 {
0285 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&self.promise() << " promise final suspend will exit");
0286 }
0287 return self.promise().continuation ? self.promise().continuation : noop_coroutine();
0288 }
0289 #else
0290 void await_suspend(coroutine_handle<outcome_promise_type> self)
0291 {
0292 if(self.promise().continuation)
0293 {
0294 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&self.promise() << " promise final suspend will resume coroutine " << self.promise().continuation.address());
0295 return self.promise().continuation.resume();
0296 }
0297 else
0298 {
0299 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&self.promise() << " promise final suspend will exit");
0300 }
0301 }
0302 #endif
0303 };
0304 return awaiter{};
0305 }
0306 };
0307 template <class Awaitable, bool suspend_initial, bool use_atomic> struct outcome_promise_type<Awaitable, suspend_initial, use_atomic, true>
0308 {
0309 using container_type = void;
0310 using result_set_type = std::conditional_t<use_atomic, std::atomic<bool>, fake_atomic<bool>>;
0311 result_set_type result_set{false}, pending_first_resumption{is_initially_suspended};
0312 coroutine_handle<> continuation;
0313
0314 static constexpr bool is_initially_suspended = suspend_initial;
0315 static constexpr bool is_using_atomics = use_atomic;
0316
0317 outcome_promise_type() { BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(this << " promise constructed"); }
0318 outcome_promise_type(const outcome_promise_type &) = delete;
0319 outcome_promise_type(outcome_promise_type &&) = delete;
0320 outcome_promise_type &operator=(const outcome_promise_type &) = delete;
0321 outcome_promise_type &operator=(outcome_promise_type &&) = delete;
0322 ~outcome_promise_type() = default;
0323 auto get_return_object()
0324 {
0325 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(this << " promise returns awaitable");
0326 return Awaitable{*this};
0327 }
0328 void return_void() noexcept
0329 {
0330 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(this << " promise returns void");
0331 BOOST_OUTCOME_ASSERT(!result_set.load(std::memory_order_acquire));
0332 result_set.store(true, std::memory_order_release);
0333 }
0334 void unhandled_exception()
0335 {
0336 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(this << " promise unhandled exception");
0337 BOOST_OUTCOME_ASSERT(!result_set.load(std::memory_order_acquire));
0338 std::rethrow_exception(std::current_exception());
0339 }
0340 auto initial_suspend() noexcept
0341 {
0342 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(this << " promise initial suspend = " << suspend_initial);
0343 struct awaiter
0344 {
0345 constexpr bool await_ready() noexcept { return !suspend_initial; }
0346 void await_resume() noexcept {}
0347 void await_suspend(coroutine_handle<> ) noexcept {}
0348 };
0349 return awaiter{};
0350 }
0351 auto final_suspend() noexcept
0352 {
0353 struct awaiter
0354 {
0355
0356
0357 constexpr bool await_ready() noexcept { return false; }
0358 void await_resume() noexcept {}
0359 #if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
0360 coroutine_handle<> await_suspend(coroutine_handle<outcome_promise_type> self) noexcept
0361 {
0362 if(self.promise().continuation)
0363 {
0364 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&self.promise() << " promise final suspend will resume coroutine " << self.promise().continuation.address());
0365 }
0366 else
0367 {
0368 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&self.promise() << " promise final suspend will exit");
0369 }
0370 return self.promise().continuation ? self.promise().continuation : noop_coroutine();
0371 }
0372 #else
0373 void await_suspend(coroutine_handle<outcome_promise_type> self)
0374 {
0375 if(self.promise().continuation)
0376 {
0377 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&self.promise() << " promise final suspend will resume coroutine " << self.promise().continuation.address());
0378 return self.promise().continuation.resume();
0379 }
0380 else
0381 {
0382 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&self.promise() << " promise final suspend will exit");
0383 }
0384 }
0385 #endif
0386 };
0387 return awaiter{};
0388 }
0389 };
0390 template <class Awaitable, bool suspend_initial, bool use_atomic>
0391 constexpr inline auto move_result_from_promise_if_not_void(outcome_promise_type<Awaitable, suspend_initial, use_atomic, false> &p)
0392 {
0393 return static_cast<typename Awaitable::container_type &&>(p.result);
0394 }
0395 template <class Awaitable, bool suspend_initial, bool use_atomic>
0396 constexpr inline void move_result_from_promise_if_not_void(outcome_promise_type<Awaitable, suspend_initial, use_atomic, true> & )
0397 {
0398 }
0399
0400 template <class Cont, class Executor, bool suspend_initial, bool use_atomic> struct BOOST_OUTCOME_NODISCARD awaitable
0401 {
0402 using container_type = Cont;
0403 using value_type = Cont;
0404 using executor_type = Executor;
0405 using promise_type = outcome_promise_type<awaitable, suspend_initial, use_atomic, std::is_void<container_type>::value>;
0406 coroutine_handle<promise_type> _h;
0407
0408 awaitable(awaitable &&o) noexcept
0409 : _h(static_cast<coroutine_handle<promise_type> &&>(o._h))
0410 {
0411 o._h = nullptr;
0412 }
0413 awaitable(const awaitable &o) = delete;
0414 awaitable &operator=(awaitable &&) = delete;
0415 awaitable &operator=(const awaitable &) = delete;
0416 ~awaitable()
0417 {
0418 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&_h.promise() << " awaitable destructs");
0419 if(_h)
0420 {
0421 _h.destroy();
0422 }
0423 }
0424 explicit awaitable(promise_type &p)
0425 : _h(coroutine_handle<promise_type>::from_promise(p))
0426 {
0427 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&_h.promise() << " awaitable constructs for coroutine " << _h.address()
0428 << " shall resume on first suspend = " << promise_type::is_initially_suspended);
0429 }
0430 bool valid() const noexcept { return _h != nullptr; }
0431 bool await_ready() noexcept
0432 {
0433 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&_h.promise() << " await_ready = " << _h.promise().result_set.load(std::memory_order_acquire));
0434 return _h.promise().result_set.load(std::memory_order_acquire);
0435 }
0436 container_type await_resume()
0437 {
0438 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&_h.promise() << " await_resume");
0439 BOOST_OUTCOME_ASSERT(_h.promise().result_set.load(std::memory_order_acquire));
0440 if(!_h.promise().result_set.load(std::memory_order_acquire))
0441 {
0442 std::terminate();
0443 }
0444 return detail::move_result_from_promise_if_not_void(_h.promise());
0445 }
0446 #if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
0447 coroutine_handle<> await_suspend(coroutine_handle<> cont) noexcept
0448 {
0449 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&_h.promise() << " await_suspend suspends coroutine " << cont.address());
0450 auto &p = _h.promise();
0451 p.continuation = cont;
0452 bool expected = true;
0453 if(p.pending_first_resumption.compare_exchange_strong(expected, false, std::memory_order_acq_rel, std::memory_order_relaxed))
0454 {
0455 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&_h.promise()
0456 << " await_suspend does one time first resumption of initially suspended coroutine " << _h.address());
0457 return _h;
0458 }
0459 return noop_coroutine();
0460 }
0461 #else
0462 void await_suspend(coroutine_handle<> cont)
0463 {
0464 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&_h.promise() << " await_suspend suspends coroutine " << cont.address());
0465 auto &p = _h.promise();
0466 p.continuation = cont;
0467 bool expected = true;
0468 if(p.pending_first_resumption.compare_exchange_strong(expected, false, std::memory_order_acq_rel, std::memory_order_relaxed))
0469 {
0470 BOOST_OUTCOME_V2_AWAITABLES_DEBUG_PRINTER(&_h.promise()
0471 << " await_suspend does one time first resumption of initially suspended coroutine " << _h.address());
0472 _h.resume();
0473 }
0474 }
0475 #endif
0476 };
0477
0478 template <class ContType, class Executor, bool suspend_initial, bool use_atomic> struct generator
0479 {
0480 using container_type = ContType;
0481 using value_type = ContType;
0482 using executor_type = Executor;
0483 class promise_type
0484 {
0485 friend struct generator;
0486 using result_set_type = std::conditional_t<use_atomic, std::atomic<int8_t>, fake_atomic<int8_t>>;
0487 union
0488 {
0489 BOOST_OUTCOME_V2_NAMESPACE::detail::empty_type _default{};
0490 container_type result;
0491 };
0492 result_set_type result_set{0};
0493 coroutine_handle<> continuation;
0494
0495 public:
0496 promise_type() {}
0497 promise_type(const promise_type &) = delete;
0498 promise_type(promise_type &&) = delete;
0499 promise_type &operator=(const promise_type &) = delete;
0500 promise_type &operator=(promise_type &&) = delete;
0501 ~promise_type()
0502 {
0503 if(result_set.load(std::memory_order_acquire) == 1)
0504 {
0505 result.~container_type();
0506 }
0507 }
0508
0509 auto get_return_object()
0510 {
0511 return generator{*this};
0512 }
0513 void return_void() noexcept
0514 {
0515 BOOST_OUTCOME_ASSERT(result_set.load(std::memory_order_acquire) >= 0);
0516 if(result_set.load(std::memory_order_acquire) == 1)
0517 {
0518 result.~container_type();
0519 }
0520 result_set.store(-1, std::memory_order_release);
0521 }
0522 suspend_always yield_value(container_type &&value)
0523 {
0524 BOOST_OUTCOME_ASSERT(result_set.load(std::memory_order_acquire) >= 0);
0525 if(result_set.load(std::memory_order_acquire) == 1)
0526 {
0527 result.~container_type();
0528 }
0529 new(&result) container_type(static_cast<container_type &&>(value));
0530 result_set.store(1, std::memory_order_release);
0531 return {};
0532 }
0533 suspend_always yield_value(const container_type &value)
0534 {
0535 BOOST_OUTCOME_ASSERT(result_set.load(std::memory_order_acquire) >= 0);
0536 if(result_set.load(std::memory_order_acquire) == 1)
0537 {
0538 result.~container_type();
0539 }
0540 new(&result) container_type(value);
0541 result_set.store(1, std::memory_order_release);
0542 return {};
0543 }
0544 void unhandled_exception()
0545 {
0546 BOOST_OUTCOME_ASSERT(result_set.load(std::memory_order_acquire) >= 0);
0547 if(result_set.load(std::memory_order_acquire) == 1)
0548 {
0549 result.~container_type();
0550 }
0551 #ifndef BOOST_NO_EXCEPTIONS
0552 auto e = std::current_exception();
0553 auto ec = detail::error_from_exception(static_cast<decltype(e) &&>(e), {});
0554
0555 if(!detail::error_is_set(ec) || !detail::try_set_error(static_cast<decltype(ec) &&>(ec), &result))
0556 {
0557 detail::set_or_rethrow(e, &result);
0558 }
0559 #else
0560 std::terminate();
0561 #endif
0562 result_set.store(1, std::memory_order_release);
0563 }
0564 auto initial_suspend() noexcept
0565 {
0566 struct awaiter
0567 {
0568 bool await_ready() noexcept { return !suspend_initial; }
0569 void await_resume() noexcept {}
0570 void await_suspend(coroutine_handle<> ) noexcept {}
0571 };
0572 return awaiter{};
0573 }
0574 auto final_suspend() noexcept
0575 {
0576 struct awaiter
0577 {
0578 bool await_ready() noexcept { return false; }
0579 void await_resume() noexcept {}
0580 #if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
0581 coroutine_handle<> await_suspend(coroutine_handle<promise_type> self) noexcept
0582 {
0583 return self.promise().continuation ? self.promise().continuation : noop_coroutine();
0584 }
0585 #else
0586 void await_suspend(coroutine_handle<promise_type> self)
0587 {
0588 if(self.promise().continuation)
0589 {
0590 return self.promise().continuation.resume();
0591 }
0592 }
0593 #endif
0594 };
0595 return awaiter{};
0596 }
0597 };
0598 coroutine_handle<promise_type> _h;
0599
0600 generator(generator &&o) noexcept
0601 : _h(static_cast<coroutine_handle<promise_type> &&>(o._h))
0602 {
0603 o._h = nullptr;
0604 }
0605 generator(const generator &o) = delete;
0606 generator &operator=(generator &&) = delete;
0607 generator &operator=(const generator &) = delete;
0608 ~generator()
0609 {
0610 if(_h)
0611 {
0612 _h.destroy();
0613 }
0614 }
0615 explicit generator(promise_type &p)
0616 : _h(coroutine_handle<promise_type>::from_promise(p))
0617 {
0618 }
0619 explicit operator bool() const
0620 {
0621 return valid();
0622 }
0623 bool valid() const
0624 {
0625 auto &p = _h.promise();
0626 if(p.result_set.load(std::memory_order_acquire) == 0)
0627 {
0628 const_cast<generator *>(this)->_h();
0629 }
0630 return p.result_set.load(std::memory_order_acquire) >= 0;
0631 }
0632 container_type operator()()
0633 {
0634 auto &p = _h.promise();
0635 if(p.result_set.load(std::memory_order_acquire) == 0)
0636 {
0637 _h();
0638 }
0639 BOOST_OUTCOME_ASSERT(p.result_set.load(std::memory_order_acquire) >= 0);
0640 if(p.result_set.load(std::memory_order_acquire) < 0)
0641 {
0642 std::terminate();
0643 }
0644 container_type ret(static_cast<container_type &&>(p.result));
0645 p.result.~container_type();
0646 p.result_set.store(0, std::memory_order_release);
0647 return ret;
0648 }
0649 #if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
0650 coroutine_handle<> await_suspend(coroutine_handle<> cont) noexcept
0651 {
0652 _h.promise().continuation = cont;
0653 return _h;
0654 }
0655 #else
0656 void await_suspend(coroutine_handle<> cont)
0657 {
0658 _h.promise().continuation = cont;
0659 _h.resume();
0660 }
0661 #endif
0662 };
0663 #endif
0664 }
0665
0666 }
0667
0668 BOOST_OUTCOME_V2_NAMESPACE_END
0669
0670 #endif
0671
0672 #ifdef BOOST_OUTCOME_FOUND_COROUTINE_HEADER
0673 BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_EXPORT_BEGIN
0674
0675
0676
0677 template <class T, class Executor = void> using eager = BOOST_OUTCOME_V2_NAMESPACE::awaitables::detail::awaitable<T, Executor, false, false>;
0678
0679
0680
0681
0682 template <class T, class Executor = void> using atomic_eager = BOOST_OUTCOME_V2_NAMESPACE::awaitables::detail::awaitable<T, Executor, false, true>;
0683
0684
0685
0686
0687 template <class T, class Executor = void> using lazy = BOOST_OUTCOME_V2_NAMESPACE::awaitables::detail::awaitable<T, Executor, true, false>;
0688
0689
0690
0691
0692 template <class T, class Executor = void> using atomic_lazy = BOOST_OUTCOME_V2_NAMESPACE::awaitables::detail::awaitable<T, Executor, true, true>;
0693
0694
0695
0696
0697 template <class T, class Executor = void> using generator = BOOST_OUTCOME_V2_NAMESPACE::awaitables::detail::generator<T, Executor, true, false>;
0698
0699 BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_END
0700 #endif