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
70 struct state_generator_t : public state_base_t
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 #if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
154 constexpr
155 #endif
156 (_offset_of(state_future_t, _is_future) - _offset_of(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
221 using state_future_t::lock_type;
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
272 using state_future_t::lock_type;
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