// // Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_COBALT_GENERATOR_HPP #define BOOST_COBALT_GENERATOR_HPP #include namespace boost::cobalt { // tag::outline[] template struct [[nodiscard]] generator // end::outline[] : detail::generator_base // tag::outline[] { // Movable generator(generator &&lhs) noexcept = default; generator& operator=(generator &&) noexcept = default; // True until it co_returns & is co_awaited after <1> explicit operator bool() const; // Cancel the generator. <3> void cancel(asio::cancellation_type ct = asio::cancellation_type::all); // Check if a value is available bool ready() const; // Get the returned value. If !ready() this function has undefined behaviour. Yield get(); // Cancel & detach the generator. ~generator(); // end::outline[] using promise_type = detail::generator_promise; generator(const generator &) = delete; generator& operator=(const generator &) = delete; private: template friend struct detail::generator_base; template friend struct detail::generator_promise; generator(detail::generator_promise * generator) : receiver_(generator->receiver, generator->signal) { } detail::generator_receiver receiver_; /* tag::outline[] // an awaitable that results in value of `Yield`. using __generator_awaitable__ = __unspecified__; // Present when `Push` != `void` __generator_awaitable__ operator()( Push && push); __generator_awaitable__ operator()(const Push & push); // Present when `Push` == `void`, i.e. can `co_await` the generator directly. __generator_awaitable__ operator co_await (); // <2> end::outline[] */ // tag::outline[] }; // end::outline[] template inline generator::operator bool() const { return !receiver_.done || receiver_.result || receiver_.exception; } template inline void generator::cancel(asio::cancellation_type ct) { if (!receiver_.done && receiver_.reference == &receiver_) receiver_.cancel_signal.emit(ct); } template inline bool generator::ready() const { return receiver_.result || receiver_.exception; } template inline Yield generator::get() { BOOST_ASSERT(ready()); receiver_.rethrow_if(); return receiver_.get_result(); } template inline generator::~generator() { cancel(); } } #endif //BOOST_COBALT_GENERATOR_HPP