1//
2// Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7
8#ifndef BOOST_COBALT_GENERATOR_HPP
9#define BOOST_COBALT_GENERATOR_HPP
10
11#include <boost/cobalt/detail/generator.hpp>
12
13
14namespace boost::cobalt
15{
16
17// tag::outline[]
18template<typename Yield, typename Push = void>
19struct [[nodiscard]] generator
20// end::outline[]
21 : detail::generator_base<Yield, Push>
22// tag::outline[]
23{
24 // Movable
25
26 generator(generator &&lhs) noexcept = default;
27 generator& operator=(generator &&) noexcept = default;
28
29 // True until it co_returns & is co_awaited after <1>
30 explicit operator bool() const;
31
32 // Cancel the generator. <3>
33 void cancel(asio::cancellation_type ct = asio::cancellation_type::all);
34
35 // Check if a value is available
36 bool ready() const;
37
38 // Get the returned value. If !ready() this function has undefined behaviour.
39 Yield get();
40
41 // Cancel & detach the generator.
42 ~generator();
43
44 // end::outline[]
45 using promise_type = detail::generator_promise<Yield, Push>;
46
47 generator(const generator &) = delete;
48 generator& operator=(const generator &) = delete;
49
50
51 private:
52 template<typename, typename>
53 friend struct detail::generator_base;
54 template<typename, typename>
55 friend struct detail::generator_promise;
56
57 generator(detail::generator_promise<Yield, Push> * generator) : receiver_(generator->receiver, generator->signal)
58 {
59 }
60 detail::generator_receiver<Yield, Push> receiver_;
61
62 /* tag::outline[]
63 // an awaitable that results in value of `Yield`.
64 using __generator_awaitable__ = __unspecified__;
65
66 // Present when `Push` != `void`
67 __generator_awaitable__ operator()( Push && push);
68 __generator_awaitable__ operator()(const Push & push);
69
70 // Present when `Push` == `void`, i.e. can `co_await` the generator directly.
71 __generator_awaitable__ operator co_await (); // <2>
72 end::outline[]
73 */
74
75
76// tag::outline[]
77
78};
79// end::outline[]
80
81
82
83template<typename Yield, typename Push >
84inline generator<Yield, Push>::operator bool() const
85{
86 return !receiver_.done || receiver_.result || receiver_.exception;
87}
88
89template<typename Yield, typename Push >
90inline void generator<Yield, Push>::cancel(asio::cancellation_type ct)
91{
92 if (!receiver_.done && receiver_.reference == &receiver_)
93 receiver_.cancel_signal.emit(ct);
94}
95
96template<typename Yield, typename Push >
97inline bool generator<Yield, Push>::ready() const { return receiver_.result || receiver_.exception; }
98
99template<typename Yield, typename Push >
100inline Yield generator<Yield, Push>::get()
101{
102 BOOST_ASSERT(ready());
103 receiver_.rethrow_if();
104 return receiver_.get_result();
105}
106
107template<typename Yield, typename Push >
108inline generator<Yield, Push>::~generator() { cancel(); }
109
110
111}
112
113#endif //BOOST_COBALT_GENERATOR_HPP
114

source code of boost/libs/cobalt/include/boost/cobalt/generator.hpp