1#ifndef C16AFA99_7780_4436_8BC0_60F24EF771A4
2#define C16AFA99_7780_4436_8BC0_60F24EF771A4
45template<
typename Result>
59 using value_type = std::remove_reference_t<Result>;
61 using pointer = std::add_pointer_t<value_type>;
100 [[nodiscard]]
constexpr auto initial_suspend()
const noexcept {
return std::suspend_always{}; }
111 auto final_suspend()
noexcept
113 this->m_current_value =
nullptr;
114 return yield_op{this->m_consumer};
125 void unhandled_exception()
noexcept { this->m_exception = std::current_exception(); }
132 constexpr void return_void()
const noexcept {}
145 auto yield_value(value_type& value)
noexcept
147 this->m_current_value = std::addressof(value);
148 return yield_op{this->m_consumer};
164 auto yield_value(std::add_rvalue_reference_t<std::remove_cv_t<value_type>> value)
noexcept
166 this->m_current_value = std::addressof(value);
167 return yield_op{this->m_consumer};
177 [[nodiscard]]
constexpr std::add_lvalue_reference_t<value_type> value()
const noexcept
179 return *this->m_current_value;
187 [[nodiscard]]
constexpr bool finished()
const noexcept {
return this->m_current_value ==
nullptr; }
198 void rethrow_if_unhandled_exception()
200 if (this->m_exception) {
201 std::rethrow_exception(std::move(this->m_exception));
213 void set_consumer(std::coroutine_handle<> consumer)
noexcept { this->m_consumer = consumer; }
217 pointer m_current_value =
nullptr;
219 std::coroutine_handle<> m_consumer;
221 std::exception_ptr m_exception =
nullptr;
236 constexpr explicit yield_op(std::coroutine_handle<> consumer) noexcept : m_consumer(consumer) {}
245 [[nodiscard]]
constexpr bool await_ready()
const noexcept {
return false; }
255 [[nodiscard]]
constexpr auto await_suspend([[maybe_unused]] std::coroutine_handle<> h)
const noexcept
257 return this->m_consumer;
265 constexpr void await_resume()
const noexcept {}
269 std::coroutine_handle<> m_consumer;
307 constexpr advance_op() noexcept : m_promise(
nullptr), m_producer(
nullptr) {}
316 explicit advance_op(std::coroutine_handle<promise_type> producer) noexcept
317 : m_promise(std::addressof(producer.promise())), m_producer(producer)
332 [[nodiscard]]
constexpr bool await_ready()
const noexcept {
return this->m_promise ==
nullptr; }
342 constexpr std::coroutine_handle<> await_suspend(std::coroutine_handle<> consumer)
noexcept
344 this->m_promise->set_consumer(consumer);
345 return this->m_producer;
366 if (this->m_promise ==
nullptr) {
370 if (this->m_promise->finished()) {
371 this->m_promise->rethrow_if_unhandled_exception();
375 return iterator{std::coroutine_handle<promise_type>::from_promise(*this->m_promise)};
382 std::coroutine_handle<> m_producer;
398 using value_type = std::remove_reference_t<Result>;
400 using reference = std::add_lvalue_reference_t<value_type>;
402 using pointer = std::add_pointer_t<value_type>;
411 explicit iterator(std::coroutine_handle<promise_type> coroutine) noexcept : m_coroutine(coroutine) {}
425 if (detail::is_good_handle(this->m_coroutine)) {
426 return advance_op{this->m_coroutine};
443 if (detail::is_good_handle(this->m_coroutine)) [[likely]] {
444 return this->m_coroutine.promise().value();
466 friend bool operator==(
const iterator& it, [[maybe_unused]] std::default_sentinel_t sentinel)
noexcept
468 return !detail::is_good_handle(it.m_coroutine);
484 return this->m_coroutine == other.m_coroutine ||
485 (!detail::is_good_handle(this->m_coroutine) && !detail::is_good_handle(other.m_coroutine));
489 std::coroutine_handle<promise_type> m_coroutine;
525 if (this->m_coroutine) {
526 this->m_coroutine.destroy();
544 if (
this != std::addressof(other)) {
545 if (this->m_coroutine) {
546 this->m_coroutine.destroy();
549 this->m_coroutine = std::exchange(other.m_coroutine,
nullptr);
577 if (!detail::is_good_handle(this->m_coroutine)) {
578 return typename iterator::advance_op();
581 return typename iterator::advance_op{this->m_coroutine};
591 [[nodiscard]]
constexpr auto end() const noexcept {
return std::default_sentinel; }
594 std::coroutine_handle<promise_type> m_coroutine;
602 : m_coroutine(std::coroutine_handle<promise_type>::from_promise(promise))
606template<
typename AsyncGenerator,
typename Callable>
609 auto it =
co_await gen.begin();
610 auto end = gen.end();
613 std::invoke(std::forward<Callable>(callable), *it);
An input iterator that asynchronously produces values of type Result.
friend bool operator==(const iterator &it, std::default_sentinel_t sentinel) noexcept
Compares the iterator it with the sentinel sentinel.
std::input_iterator_tag iterator_concept
The strongest iterator concept supported by the iterator.
advance_op operator++()
Advances the iterator to the next value.
std::ptrdiff_t difference_type
Difference between the addresses of any two elements in the controlled sequence.
bool operator==(const iterator &other) const noexcept
Compares two iterators for equality.
reference operator*() const
Dereferences the iterator to obtain the current value.
The promise type of the generator.
An asynchronous generator that produces values of type Result.
~async_generator()
Destructor.
constexpr async_generator() noexcept=default
Default constructor.
async_generator & operator=(async_generator &&other) noexcept
Move assignment operator.
constexpr auto end() const noexcept
Returns a sentinel iterator.
auto begin() noexcept
Returns an awaitable iterator to the current item of the generator.
Exception thrown when accessing a result that is not available.
Internal utility functions for coroutine handling.
Custom exception classes for coroutine handling.
task< void > async_for_each(AsyncGenerator gen, Callable callable)