Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-14 08:27:12

0001 //
0002 // Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #ifndef BOOST_COBALT_GENERATOR_HPP
0009 #define BOOST_COBALT_GENERATOR_HPP
0010 
0011 #include <boost/cobalt/detail/generator.hpp>
0012 
0013 
0014 namespace boost::cobalt
0015 {
0016 
0017 // tag::outline[]
0018 template<typename Yield, typename Push = void>
0019 struct [[nodiscard]] generator
0020 // end::outline[]
0021      : detail::generator_base<Yield, Push>
0022 // tag::outline[]
0023 {
0024   // Movable
0025 
0026   generator(generator &&lhs) noexcept = default;
0027   generator& operator=(generator &&) noexcept;
0028 
0029   // True until it co_returns & is co_awaited after <1>
0030   explicit operator bool() const;
0031 
0032   // Cancel the generator. <3>
0033   void cancel(asio::cancellation_type ct = asio::cancellation_type::all);
0034 
0035   // Check if a value is available
0036   bool ready() const;
0037 
0038   // Get the returned value. If !ready() this function has undefined behaviour.
0039   Yield get();
0040 
0041   // Cancel & detach the generator.
0042   ~generator();
0043 
0044   // end::outline[]
0045   using promise_type = detail::generator_promise<Yield, Push>;
0046 
0047   generator(const generator &) = delete;
0048   generator& operator=(const generator &) = delete;
0049 
0050   constexpr generator(noop<Yield> n) : receiver_(std::move(n)){}
0051 
0052  private:
0053   template<typename, typename>
0054   friend struct detail::generator_base;
0055   template<typename, typename>
0056   friend struct detail::generator_promise;
0057 
0058   generator(detail::generator_promise<Yield, Push> * generator) : receiver_(generator->receiver, generator->signal)
0059   {
0060   }
0061   detail::generator_receiver<Yield, Push> receiver_;
0062 
0063   /* tag::outline[]
0064   // an awaitable that results in value of `Yield`.
0065   using __generator_awaitable__ = __unspecified__;
0066 
0067   // Present when `Push` != `void`
0068   __generator_awaitable__ operator()(      Push && push);
0069   __generator_awaitable__ operator()(const Push &  push);
0070 
0071   // Present when `Push` == `void`, i.e. can `co_await` the generator directly.
0072   __generator_awaitable__ operator co_await (); // <2>
0073    end::outline[]
0074    */
0075 
0076 
0077 // tag::outline[]
0078 
0079 };
0080 // end::outline[]
0081 
0082 
0083 
0084 template<typename Yield, typename Push >
0085 inline generator<Yield, Push>::operator bool() const
0086 {
0087   return !receiver_.done || receiver_.result || receiver_.exception;
0088 }
0089 
0090 template<typename Yield, typename Push >
0091 inline void generator<Yield, Push>::cancel(asio::cancellation_type ct)
0092 {
0093   if (!receiver_.done && *receiver_.reference == &receiver_)
0094     receiver_.cancel_signal->emit(ct);
0095 }
0096 
0097 template<typename Yield, typename Push >
0098 inline bool generator<Yield, Push>::ready() const  { return receiver_.result || receiver_.exception; }
0099 
0100 template<typename Yield, typename Push >
0101 inline Yield generator<Yield, Push>::get()
0102 {
0103   BOOST_ASSERT(ready());
0104   receiver_.rethrow_if();
0105   return receiver_.get_result();
0106 }
0107 
0108 template<typename Yield, typename Push >
0109 inline generator<Yield, Push>::~generator() { cancel(); }
0110 
0111 template<typename Yield, typename Push >
0112 inline
0113 generator<Yield, Push>& generator<Yield, Push>::operator=(generator && lhs) noexcept
0114 {
0115   cancel();
0116   receiver_ = std::move(lhs.receiver_);
0117   return *this;
0118 }
0119 
0120 }
0121 
0122 #endif //BOOST_COBALT_GENERATOR_HPP