librf
state.h
1 #pragma once
2 
3 namespace resumef
4 {
8  struct state_base_t
9  {
10  using _Alloc_char = std::allocator<char>;
11  private:
12  std::atomic<intptr_t> _count{0};
13  public:
14  void lock()
15  {
16  ++_count;
17  }
18  void unlock()
19  {
20  if (--_count == 0)
21  {
22  destroy_deallocate();
23  }
24  }
25  protected:
26  scheduler_t* _scheduler = nullptr;
27  //可能来自协程里的promise产生的,则经过co_await操作后,_coro在初始时不会为nullptr。
28  //也可能来自awaitable_t,如果
29  // 一、经过co_await操作后,_coro在初始时不会为nullptr。
30  // 二、没有co_await操作,直接加入到了调度器里,则_coro在初始时为nullptr。调度器需要特殊处理此种情况。
31  coroutine_handle<> _coro;
32 
33  virtual ~state_base_t();
34  private:
35  virtual void destroy_deallocate();
36  public:
37  virtual void resume() = 0;
38  virtual bool has_handler() const noexcept = 0;
39  virtual state_base_t* get_parent() const noexcept;
40 
41  void set_scheduler(scheduler_t* sch)
42  {
43  _scheduler = sch;
44  }
45  coroutine_handle<> get_handler() const
46  {
47  return _coro;
48  }
49 
50  state_base_t* get_root() const noexcept
51  {
52  state_base_t* root = const_cast<state_base_t*>(this);
53  state_base_t* next = root->get_parent();
54  while (next != nullptr)
55  {
56  root = next;
57  next = next->get_parent();
58  }
59  return root;
60  }
61  scheduler_t* get_scheduler() const
62  {
63  return get_root()->_scheduler;
64  }
65  };
66 
71  {
72  private:
73  virtual void destroy_deallocate() override;
74  state_generator_t() = default;
75  public:
76  virtual void resume() override;
77  virtual bool has_handler() const noexcept override;
78 
79  bool switch_scheduler_await_suspend(scheduler_t* sch);
80 
81  void set_initial_suspend(coroutine_handle<> handler)
82  {
83  _coro = handler;
84  }
85 
86 #if RESUMEF_INLINE_STATE
87  static state_generator_t* _Construct(void* _Ptr)
88  {
89  return new(_Ptr) state_generator_t();
90  }
91 #endif
92  static state_generator_t* _Alloc_state();
93  };
94 
98  struct state_future_t : public state_base_t
99  {
100  enum struct initor_type : uint8_t
101  {
102  None,
103  Initial,
104  Final
105  };
106  enum struct result_type : uint8_t
107  {
108  None,
109  Value,
110  Exception,
111  };
112 
113  //typedef std::recursive_mutex lock_type;
114  typedef spinlock lock_type;
115  protected:
116  mutable lock_type _mtx;
117  coroutine_handle<> _initor;
118  state_future_t* _parent = nullptr;
119 #if RESUMEF_DEBUG_COUNTER
120  intptr_t _id;
121 #endif
122  uint32_t _alloc_size = 0;
123  //注意:_has_value对齐到 4 Byte上,后面必须紧跟 _is_future变量。两者能组合成一个uint16_t数据。
124  std::atomic<result_type> _has_value{ result_type::None };
125  bool _is_future;
126  initor_type _is_initor = initor_type::None;
127  static_assert(sizeof(std::atomic<result_type>) == 1);
128  static_assert(alignof(std::atomic<result_type>) == 1);
129  static_assert(sizeof(bool) == 1);
130  static_assert(alignof(bool) == 1);
131  static_assert(sizeof(std::atomic<initor_type>) == 1);
132  static_assert(alignof(std::atomic<initor_type>) == 1);
133  protected:
134  explicit state_future_t(bool awaitor)
135  {
136 #if RESUMEF_DEBUG_COUNTER
137  _id = ++g_resumef_state_id;
138 #endif
139  _is_future = !awaitor;
140  }
141  public:
142  virtual void destroy_deallocate() override;
143  virtual void resume() override;
144  virtual bool has_handler() const noexcept override;
145  virtual state_base_t* get_parent() const noexcept override;
146 
147  inline bool is_ready() const noexcept
148  {
149 #pragma warning(disable : 6326) //warning C6326: Potential comparison of a constant with another constant.
150  //msvc认为是constexpr表达式(不写还给警告),然而,clang不这么认为。
151  //放弃constexpr,反正合格的编译器都会优化掉这个if判断的。
152  if
153 #ifndef __clang__
154  constexpr
155 #endif
156  (offsetof(state_future_t, _is_future) - offsetof(state_future_t, _has_value) == 1)
157  return 0 != reinterpret_cast<const std::atomic<uint16_t> &>(_has_value).load(std::memory_order_acquire);
158  else
159  return _has_value.load(std::memory_order_acquire) != result_type::None || _is_future;
160 #pragma warning(default : 6326)
161  }
162  inline bool has_handler_skip_lock() const noexcept
163  {
164  return (bool)_coro || _is_initor != initor_type::None;
165  }
166 
167  inline uint32_t get_alloc_size() const noexcept
168  {
169  return _alloc_size;
170  }
171 
172  inline bool future_await_ready() noexcept
173  {
174  //scoped_lock<lock_type> __guard(this->_mtx);
175  return _has_value.load(std::memory_order_acquire) != result_type::None;
176  }
177  template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>>
178  void future_await_suspend(coroutine_handle<_PromiseT> handler);
179 
180  bool switch_scheduler_await_suspend(scheduler_t* sch);
181 
182  template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>>
183  void promise_initial_suspend(coroutine_handle<_PromiseT> handler);
184  template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>>
185  void promise_final_suspend(coroutine_handle<_PromiseT> handler);
186 
187 #if RESUMEF_INLINE_STATE
188  template<class _Sty>
189  static _Sty* _Construct(void* _Ptr, size_t _Size)
190  {
191  _Sty* st = new(_Ptr) _Sty(false);
192  st->_alloc_size = static_cast<uint32_t>(_Size);
193 
194  return st;
195  }
196 #endif
197  template<class _Sty>
198  static inline _Sty* _Alloc_state(bool awaitor)
199  {
200  _Alloc_char _Al;
201  size_t _Size = _Align_size<_Sty>();
202 #if RESUMEF_DEBUG_COUNTER
203  std::cout << "state_future_t::alloc, size=" << _Size << std::endl;
204 #endif
205  char* _Ptr = _Al.allocate(_Size);
206  _Sty* st = new(_Ptr) _Sty(awaitor);
207  st->_alloc_size = static_cast<uint32_t>(_Size);
208 
209  return st;
210  }
211  };
212 
216  template <typename _Ty>
217  struct state_t final : public state_future_t
218  {
219  friend state_future_t;
220 
222  using value_type = _Ty;
223  private:
224  explicit state_t(bool awaitor) :state_future_t(awaitor) {}
225  public:
226  ~state_t()
227  {
228  switch (_has_value.load(std::memory_order_acquire))
229  {
230  case result_type::Value:
231  _value.~value_type();
232  break;
233  case result_type::Exception:
234  _exception.~exception_ptr();
235  break;
236  default:
237  break;
238  }
239  }
240 
241  auto future_await_resume() -> value_type;
242  template<class _PromiseT, typename U, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>>
243  void promise_yield_value(_PromiseT* promise, U&& val);
244 
245  void set_exception(std::exception_ptr e);
246  template<typename U>
247  void set_value(U&& val);
248 
249  template<class _Exp>
250  inline void throw_exception(_Exp e)
251  {
252  set_exception(std::make_exception_ptr(std::move(e)));
253  }
254  private:
255  union
256  {
257  std::exception_ptr _exception;
258  value_type _value;
259  };
260 
261  template<typename U>
262  void set_value_internal(U&& val);
263  void set_exception_internal(std::exception_ptr e);
264  };
265 
266 #ifndef DOXYGEN_SKIP_PROPERTY
267  template <typename _Ty>
268  struct state_t<_Ty&> final : public state_future_t
269  {
270  friend state_future_t;
271 
273  using value_type = _Ty;
274  using reference_type = _Ty&;
275  private:
276  explicit state_t(bool awaitor) :state_future_t(awaitor) {}
277  public:
278  ~state_t()
279  {
280  if (_has_value.load(std::memory_order_acquire) == result_type::Exception)
281  _exception.~exception_ptr();
282  }
283 
284  auto future_await_resume()->reference_type;
285  template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>>
286  void promise_yield_value(_PromiseT* promise, reference_type val);
287 
288  void set_exception(std::exception_ptr e);
289  void set_value(reference_type val);
290 
291  template<class _Exp>
292  inline void throw_exception(_Exp e)
293  {
294  set_exception(std::make_exception_ptr(std::move(e)));
295  }
296  private:
297  union
298  {
299  std::exception_ptr _exception;
300  value_type* _value;
301  };
302 
303  void set_value_internal(reference_type val);
304  void set_exception_internal(std::exception_ptr e);
305  };
306 
307  template<>
308  struct state_t<void> final : public state_future_t
309  {
310  friend state_future_t;
311  using state_future_t::lock_type;
312  private:
313  explicit state_t(bool awaitor) :state_future_t(awaitor) {}
314  public:
315  void future_await_resume();
316  template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>>
317  void promise_yield_value(_PromiseT* promise);
318 
319  void set_exception(std::exception_ptr e);
320  void set_value();
321 
322  template<class _Exp>
323  inline void throw_exception(_Exp e)
324  {
325  set_exception(std::make_exception_ptr(std::move(e)));
326  }
327  private:
328  std::exception_ptr _exception;
329  };
330 #endif //DOXYGEN_SKIP_PROPERTY
331 }
332 
resumef::scheduler_t
协程调度器。
Definition: scheduler.h:10
resumef::state_base_t
state基类,state用于在协程的promise和future之间共享数据。
Definition: state.h:8
resumef::spinlock
一个自旋锁实现。
Definition: spinlock.h:14
resumef::state_future_t
专用于future_t<>的state基类,实现了针对于future_t<>的公共方法等。
Definition: state.h:98
resumef::state_t
专用于future_t<>的state类。
Definition: state.h:217
resumef::state_generator_t
专用于generator_t<>的state类。
Definition: state.h:70