![]() |
boost::taar::async_generator — A coroutine-based asynchronous generator of values of type T.
// In header: <boost/taar/core/async_generator.hpp> template<typename T> class async_generator { public: // types typedef std::coroutine_handle< promise_type > handle_type; typedef boost::asio::any_io_executor executor_type; typedef unspecified completion_handler_type; // member classes/structs/unions struct promise_type { // member classes/structs/unions struct final_awaiter { // public member functions bool await_ready() noexcept; void await_suspend(handle_type) noexcept; void await_resume() noexcept; }; struct yield_awaiter { // public member functions bool await_ready() noexcept; void await_suspend(handle_type) noexcept; void await_resume() noexcept; }; // public member functions async_generator get_return_object(); std::suspend_always initial_suspend() noexcept; final_awaiter final_suspend() noexcept; yield_awaiter yield_value(T); void return_void() noexcept; void unhandled_exception(); template<typename U, typename Executor> auto await_transform(boost::asio::awaitable< U, Executor >); template<typename Executor> auto await_transform(boost::asio::awaitable< void, Executor >); auto await_transform(boost::asio::this_coro::executor_t) noexcept; auto await_transform(boost::asio::this_coro::cancellation_state_t) noexcept; // public data members auto await_transform(Deferred &&d) -> decltype(this->await_transform(std::forward< Deferred >(d)(boost::asio::use_awaitable_t< executor_type >{}))) flatten_awaiter yield_value; std::optional< T > current_value_; completion_handler_type completion_handler_; std::optional< executor_type > executor_; std::exception_ptr exception_; std::optional< boost::asio::cancellation_slot > cancellation_slot_; boost::asio::cancellation_signal internal_signal_; std::optional< boost::asio::cancellation_state > cancellation_state_; std::shared_ptr< bool > alive_; std::shared_ptr< boost::asio::cancellation_signal > active_co_spawn_signal_; std::shared_ptr< boost::asio::cancellation_signal > flattening_cancel_signal_; std::optional< async_generator< T > > flattening_inner_storage_; async_generator< T > * flattening_inner_; handle_type flattening_outer_handle_; }; // public member functions async_generator(); explicit async_generator(handle_type) noexcept; async_generator(async_generator &&) noexcept; async_generator & operator=(async_generator &&) noexcept; async_generator(async_generator const &) = delete; async_generator & operator=(async_generator const &) = delete; ~async_generator(); void set_executor(executor_type); void set_cancellation_slot(boost::asio::cancellation_slot); void rethrow_if_exception(); auto next(); // private member functions template<typename Handler> void next_impl(Handler); void destroy_handle() noexcept; };
async_generator<T> is the building block for HTTP responses produced incrementally: streaming JSON, server-sent events, NDJSON, or any other body that should be written to the wire as the data becomes available.
Inside the generator body, suspend with co_yield value to produce a value. The session drives the generator with next, which returns an awaitable resolving to std::optional<T>: empty when the generator has exhausted. The generator may also co_await arbitrary asio::awaitables as long as an executor has been installed via set_executor.
async_generator<T> may yield another async_generator<T> to splice its values into the outer stream (flattening). Exceptions thrown from the generator body are stashed on the promise and rethrown from the next next call. Cancellation propagates via set_cancellation_slot.
See boost::taar::chunked_response for the variant that additionally lets the producer set the HTTP status and headers before the first chunk goes on the wire.
typename T
The yielded value type. Any type accepted by boost::taar::chunk_body_from is supported.
async_generator public member functionsasync_generator();
explicit async_generator(handle_type h) noexcept;
async_generator(async_generator && other) noexcept;
async_generator & operator=(async_generator && other) noexcept;
async_generator(async_generator const &) = delete;
async_generator & operator=(async_generator const &) = delete;
~async_generator();
void set_executor(executor_type executor);Install the executor used to drive
co_awaits and post completions. void set_cancellation_slot(boost::asio::cancellation_slot slot);Wire slot so that cancelling it cancels all pending work in the generator.
void rethrow_if_exception();If the generator body stashed an exception, rethrow and clear it.
auto next();Drive the generator forward by one step.
Returns an awaitable that resolves to a tuple (error_code, std::optional<T>). The optional is empty when the generator has finished producing values; the error code carries any transport-level failure (currently always empty, exceptions from the body are propagated by rethrow inside the coroutine).
If no executor has been installed via set_executor, the one associated with the calling coroutine is captured on the first call.