emlabcpp
modern opinionated embedded C++ library
recursive.h
Go to the documentation of this file.
1 #pragma once
23 
24 #include "./data_promise.h"
25 #include "./memory_promise.h"
27 
28 #include <coroutine>
29 
30 namespace emlabcpp::coro
31 {
32 
33 enum class wait_state : uint8_t
34 {
35  WAITING,
36  READY,
37  ERRORED
38 };
39 
41 {
42  [[nodiscard]] virtual wait_state get_state() const = 0;
43  virtual void tick() = 0;
44  virtual ~wait_interface() = default;
45 };
46 
48 {
49  [[nodiscard]] wait_state get_state() const override
50  {
51  return wait_state::READY;
52  }
53 
54  void tick() override
55  {
56  }
57 
58  [[nodiscard]] bool await_ready() const
59  {
60  return false;
61  }
62 
63  template < typename T >
64  void await_suspend( std::coroutine_handle< T > )
65  {
66  }
67 
68  void await_resume() const
69  {
70  }
71 };
72 
74 {
75  [[nodiscard]] wait_state get_state() const override
76  {
77  return wait_state::ERRORED;
78  }
79 
80  void tick() override
81  {
82  }
83 
84  [[nodiscard]] bool await_ready() const
85  {
86  return false;
87  }
88 
89  template < typename T >
90  void await_suspend( std::coroutine_handle< T > )
91  {
92  }
93 
94  void await_resume() const
95  {
96  }
97 };
98 
99 template < typename T >
101 {
102 public:
103  struct promise_type : data_promise< T >, memory_promise< promise_type >
104  {
106  {
107  return recursive_coroutine{};
108  }
109 
111  {
112  return recursive_coroutine{ handle::from_promise( *this ) };
113  }
114 
115  [[nodiscard]] std::suspend_always initial_suspend() const
116  {
117  return {};
118  }
119 
120  [[nodiscard]] std::suspend_always final_suspend() const noexcept
121  {
122  return {};
123  }
124 
125  void unhandled_exception() const
126  {
127  }
128 
129  wait_interface* iface = nullptr;
130  };
131 
132  using handle = std::coroutine_handle< promise_type >;
134 
135  recursive_coroutine() = default;
136 
137  explicit recursive_coroutine( handle const& cor )
138  : h_( cor )
139  {
140  }
141 
142  [[nodiscard]] bool done() const
143  {
144  if ( h_ )
145  return h_.done();
146  return true;
147  }
148 
149  [[nodiscard]] wait_state get_state() const override
150  {
151  if ( done() )
152  return wait_state::READY;
153  return wait_state::WAITING;
154  }
155 
156  [[nodiscard]] bool await_ready() const
157  {
158  return false;
159  }
160 
161  template < typename U >
162  void await_suspend( U const h )
163  {
164  h.promise().iface = this;
165  }
166 
168  {
169  if constexpr ( !std::is_void_v< T > )
170  return h_.promise().value;
171  }
172 
173  auto get_value()
174  {
175  return h_.promise().value;
176  }
177 
178  auto run()
179  {
180  while ( !done() )
181  tick();
182 
183  if constexpr ( !std::is_void_v< T > )
184  return h_.promise().value;
185  }
186 
187  void tick() override
188  {
189  if ( !h_ )
190  return;
191  wait_interface* iface = h_.promise().iface;
192 
193  if ( iface != nullptr ) {
194  wait_state const s = iface->get_state();
195  if ( s == wait_state::WAITING ) {
196  iface->tick();
197  return;
198  } else if ( s == wait_state::ERRORED ) {
199  h_ = owning_handle();
200  return;
201  } else {
202  // Intentionally does nothing
203  }
204  }
205  if ( !h_.done() )
206  h_();
207  }
208 
209 private:
210  owning_handle h_;
211 };
212 
213 } // namespace emlabcpp::coro
constexpr bool done() const
Definition: owning_coroutine_handle.h:70
constexpr promise_type & promise()
Definition: owning_coroutine_handle.h:80
Definition: recursive.h:101
void await_suspend(U const h)
Definition: recursive.h:162
wait_state get_state() const override
Definition: recursive.h:149
void tick() override
Definition: recursive.h:187
recursive_coroutine(handle const &cor)
Definition: recursive.h:137
bool done() const
Definition: recursive.h:142
auto await_resume()
Definition: recursive.h:167
auto run()
Definition: recursive.h:178
auto get_value()
Definition: recursive.h:173
owning_coroutine_handle< promise_type > owning_handle
Definition: recursive.h:133
std::coroutine_handle< promise_type > handle
Definition: recursive.h:132
bool await_ready() const
Definition: recursive.h:156
MIT License.
Definition: data_promise.h:27
wait_state
Definition: recursive.h:34
Definition: data_promise.h:31
T value
Definition: data_promise.h:38
Definition: recursive.h:74
void tick() override
Definition: recursive.h:80
wait_state get_state() const override
Definition: recursive.h:75
void await_resume() const
Definition: recursive.h:94
void await_suspend(std::coroutine_handle< T >)
Definition: recursive.h:90
bool await_ready() const
Definition: recursive.h:84
Definition: memory_promise.h:34
Definition: recursive.h:48
bool await_ready() const
Definition: recursive.h:58
wait_state get_state() const override
Definition: recursive.h:49
void tick() override
Definition: recursive.h:54
void await_suspend(std::coroutine_handle< T >)
Definition: recursive.h:64
void await_resume() const
Definition: recursive.h:68
static recursive_coroutine get_return_object_on_allocation_failure()
Definition: recursive.h:105
void unhandled_exception() const
Definition: recursive.h:125
wait_interface * iface
Definition: recursive.h:129
recursive_coroutine get_return_object()
Definition: recursive.h:110
std::suspend_always initial_suspend() const
Definition: recursive.h:115
std::suspend_always final_suspend() const noexcept
Definition: recursive.h:120
Definition: recursive.h:41
virtual ~wait_interface()=default
virtual wait_state get_state() const =0