基于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.3KB

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