基于C++ Coroutines提案 ‘Stackless Resumable Functions’编写的协程库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

state.cpp 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include "librf/librf.h"
  2. namespace librf
  3. {
  4. LIBRF_API state_base_t::~state_base_t()
  5. {
  6. }
  7. LIBRF_API void state_base_t::destroy_deallocate()
  8. {
  9. delete this;
  10. }
  11. LIBRF_API void state_base_t::resume()
  12. {
  13. if (likely(_coro))
  14. {
  15. coroutine_handle<> handler = _coro;
  16. _coro = nullptr;
  17. _scheduler->del_final(this);
  18. handler.resume();
  19. }
  20. }
  21. LIBRF_API bool state_base_t::has_handler() const noexcept
  22. {
  23. return (bool)_coro;
  24. }
  25. LIBRF_API state_base_t* state_base_t::get_parent() const noexcept
  26. {
  27. return nullptr;
  28. }
  29. LIBRF_API void state_future_t::destroy_deallocate()
  30. {
  31. size_t _Size = this->_alloc_size;
  32. #if RESUMEF_DEBUG_COUNTER
  33. std::cout << "destroy_deallocate, size=" << _Size << std::endl;
  34. #endif
  35. this->~state_future_t();
  36. _Alloc_char _Al;
  37. return _Al.deallocate(reinterpret_cast<char*>(this), _Size);
  38. }
  39. LIBRF_API state_generator_t* state_generator_t::_Alloc_state()
  40. {
  41. _Alloc_char _Al;
  42. size_t _Size = _Align_size<state_generator_t>();
  43. #if RESUMEF_DEBUG_COUNTER
  44. std::cout << "state_generator_t::alloc, size=" << sizeof(state_generator_t) << std::endl;
  45. #endif
  46. char* _Ptr = _Al.allocate(_Size);
  47. return new(_Ptr) state_generator_t();
  48. }
  49. LIBRF_API void state_generator_t::destroy_deallocate()
  50. {
  51. size_t _Size = _Align_size<state_generator_t>();
  52. #if RESUMEF_INLINE_STATE
  53. char* _Ptr = reinterpret_cast<char*>(this) + _Size;
  54. _Size = *reinterpret_cast<uint32_t*>(_Ptr);
  55. #endif
  56. #if RESUMEF_DEBUG_COUNTER
  57. std::cout << "destroy_deallocate, size=" << _Size << std::endl;
  58. #endif
  59. this->~state_generator_t();
  60. _Alloc_char _Al;
  61. return _Al.deallocate(reinterpret_cast<char*>(this), _Size);
  62. }
  63. LIBRF_API void state_generator_t::resume()
  64. {
  65. if (likely(_coro))
  66. {
  67. _coro.resume();
  68. if (likely(!_coro.done()))
  69. {
  70. _scheduler->add_generator(this);
  71. }
  72. else
  73. {
  74. coroutine_handle<> handler = _coro;
  75. _coro = nullptr;
  76. _scheduler->del_final(this);
  77. handler.destroy();
  78. }
  79. }
  80. }
  81. LIBRF_API bool state_generator_t::has_handler() const noexcept
  82. {
  83. return (bool)_coro;
  84. }
  85. LIBRF_API bool state_generator_t::switch_scheduler_await_suspend(scheduler_t* sch)
  86. {
  87. assert(sch != nullptr);
  88. if (_scheduler != nullptr)
  89. {
  90. if (_scheduler == sch) return false;
  91. auto task_ptr = _scheduler->del_switch(this);
  92. _scheduler = sch;
  93. if (task_ptr != nullptr)
  94. sch->add_switch(std::move(task_ptr));
  95. }
  96. else
  97. {
  98. _scheduler = sch;
  99. }
  100. return true;
  101. }
  102. LIBRF_API state_base_t* state_future_t::get_parent() const noexcept
  103. {
  104. return _parent;
  105. }
  106. LIBRF_API void state_future_t::resume()
  107. {
  108. std::unique_lock<lock_type> __guard(_mtx);
  109. if (_is_initor == initor_type::Initial)
  110. {
  111. assert((bool)_initor);
  112. coroutine_handle<> handler = _initor;
  113. _is_initor = initor_type::None;
  114. __guard.unlock();
  115. handler.resume();
  116. return;
  117. }
  118. if (_coro)
  119. {
  120. coroutine_handle<> handler = _coro;
  121. _coro = nullptr;
  122. __guard.unlock();
  123. handler.resume();
  124. return;
  125. }
  126. if (_is_initor == initor_type::Final)
  127. {
  128. assert((bool)_initor);
  129. coroutine_handle<> handler = _initor;
  130. _is_initor = initor_type::None;
  131. __guard.unlock();
  132. handler.destroy();
  133. return;
  134. }
  135. }
  136. LIBRF_API bool state_future_t::has_handler() const noexcept
  137. {
  138. scoped_lock<lock_type> __guard(this->_mtx);
  139. return has_handler_skip_lock();
  140. }
  141. LIBRF_API bool state_future_t::switch_scheduler_await_suspend(scheduler_t* sch)
  142. {
  143. assert(sch != nullptr);
  144. scoped_lock<lock_type> __guard(this->_mtx);
  145. if (_scheduler != nullptr)
  146. {
  147. if (_scheduler == sch) return false;
  148. auto task_ptr = _scheduler->del_switch(this);
  149. _scheduler = sch;
  150. if (task_ptr != nullptr)
  151. sch->add_switch(std::move(task_ptr));
  152. }
  153. else
  154. {
  155. _scheduler = sch;
  156. }
  157. if (_parent != nullptr)
  158. _parent->switch_scheduler_await_suspend(sch);
  159. return true;
  160. }
  161. LIBRF_API void state_t<void>::future_await_resume()
  162. {
  163. scoped_lock<lock_type> __guard(this->_mtx);
  164. if (this->_exception)
  165. std::rethrow_exception(std::move(this->_exception));
  166. if (this->_has_value.load(std::memory_order_acquire) == result_type::None)
  167. std::rethrow_exception(std::make_exception_ptr(future_exception{error_code::not_ready}));
  168. }
  169. LIBRF_API void state_t<void>::set_value()
  170. {
  171. scoped_lock<lock_type> __guard(this->_mtx);
  172. this->_has_value.store(result_type::Value, std::memory_order_release);
  173. scheduler_t* sch = this->get_scheduler();
  174. if (sch != nullptr)
  175. {
  176. if (this->has_handler_skip_lock())
  177. sch->add_generator(this);
  178. else
  179. sch->del_final(this);
  180. }
  181. }
  182. LIBRF_API void state_t<void>::set_exception(std::exception_ptr e)
  183. {
  184. scoped_lock<lock_type> __guard(this->_mtx);
  185. this->_exception = std::move(e);
  186. scheduler_t* sch = this->get_scheduler();
  187. if (sch != nullptr)
  188. {
  189. if (this->has_handler_skip_lock())
  190. sch->add_generator(this);
  191. else
  192. sch->del_final(this);
  193. }
  194. }
  195. }