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

event_v2.cpp 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include "librf/librf.h"
  2. namespace librf
  3. {
  4. namespace detail
  5. {
  6. LIBRF_API void state_event_t::on_cancel() noexcept
  7. {
  8. event_v2_impl** oldValue = _value.load(std::memory_order_acquire);
  9. if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel))
  10. {
  11. *oldValue = nullptr;
  12. _thandler.stop();
  13. this->_coro = nullptr;
  14. }
  15. }
  16. LIBRF_API bool state_event_t::on_notify(event_v2_impl* eptr)
  17. {
  18. event_v2_impl** oldValue = _value.load(std::memory_order_acquire);
  19. if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel))
  20. {
  21. *oldValue = eptr;
  22. _thandler.stop();
  23. assert(this->_scheduler != nullptr);
  24. if (this->_coro)
  25. this->_scheduler->add_generator(this);
  26. return true;
  27. }
  28. return false;
  29. }
  30. LIBRF_API bool state_event_t::on_timeout()
  31. {
  32. event_v2_impl** oldValue = _value.load(std::memory_order_acquire);
  33. if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel))
  34. {
  35. event_v2_impl* evt = *oldValue;
  36. if (evt != nullptr)
  37. evt->remove_wait_list(this);
  38. *oldValue = nullptr;
  39. _thandler.reset();
  40. assert(this->_scheduler != nullptr);
  41. if (this->_coro)
  42. this->_scheduler->add_generator(this);
  43. return true;
  44. }
  45. return false;
  46. }
  47. LIBRF_API void state_event_all_t::on_cancel(intptr_t idx)
  48. {
  49. scoped_lock<event_v2_impl::lock_type> lock_(_lock);
  50. if (_counter <= 0) return ;
  51. assert(idx < static_cast<intptr_t>(_values.size()));
  52. _values[idx] = sub_state_t{ nullptr, nullptr };
  53. if (--_counter == 0)
  54. {
  55. *_result = false;
  56. _thandler.stop();
  57. assert(this->_scheduler != nullptr);
  58. if (this->_coro)
  59. this->_scheduler->add_generator(this);
  60. }
  61. }
  62. LIBRF_API bool state_event_all_t::on_notify(event_v2_impl*, intptr_t idx)
  63. {
  64. scoped_lock<event_v2_impl::lock_type> lock_(_lock);
  65. if (_counter <= 0) return false;
  66. assert(idx < static_cast<intptr_t>(_values.size()));
  67. _values[idx].first = nullptr;
  68. if (--_counter == 0)
  69. {
  70. bool result = true;
  71. for (sub_state_t& sub : _values)
  72. {
  73. if (sub.second == nullptr)
  74. {
  75. result = false;
  76. break;
  77. }
  78. }
  79. *_result = result;
  80. _thandler.stop();
  81. assert(this->_scheduler != nullptr);
  82. if (this->_coro)
  83. this->_scheduler->add_generator(this);
  84. }
  85. return true;
  86. }
  87. LIBRF_API bool state_event_all_t::on_timeout()
  88. {
  89. scoped_lock<event_v2_impl::lock_type> lock_(_lock);
  90. if (_counter <= 0) return false;
  91. _counter = 0;
  92. *_result = false;
  93. _thandler.reset();
  94. for (sub_state_t& sub : _values)
  95. {
  96. if (sub.first != nullptr)
  97. {
  98. event_v2_impl* evt = sub.second;
  99. sub.second = nullptr;
  100. if (evt != nullptr)
  101. evt->remove_wait_list(sub.first);
  102. }
  103. }
  104. assert(this->_scheduler != nullptr);
  105. if (this->_coro)
  106. this->_scheduler->add_generator(this);
  107. return true;
  108. }
  109. LIBRF_API event_v2_impl::event_v2_impl(bool initially) noexcept
  110. : _counter(initially ? 1 : 0)
  111. {
  112. }
  113. template<class _Ty, class _Ptr>
  114. static auto try_pop_list(intrusive_link_queue<_Ty, _Ptr>& list)
  115. {
  116. return list.try_pop();
  117. }
  118. template<class _Ptr>
  119. static _Ptr try_pop_list(std::list<_Ptr>& list)
  120. {
  121. if (!list.empty())
  122. {
  123. _Ptr ptr = list.front();
  124. list.pop_front();
  125. return ptr;
  126. }
  127. return nullptr;
  128. }
  129. template<class _Ty, class _Ptr>
  130. static void clear_list(intrusive_link_queue<_Ty, _Ptr>& list)
  131. {
  132. for (; list.try_pop() != nullptr;);
  133. }
  134. template<class _Ptr>
  135. static void clear_list(std::list<_Ptr>& list)
  136. {
  137. list.clear();
  138. }
  139. LIBRF_API event_v2_impl::~event_v2_impl()
  140. {
  141. clear_list(_wait_awakes);
  142. }
  143. LIBRF_API void event_v2_impl::signal_all() noexcept
  144. {
  145. scoped_lock<lock_type> lock_(_lock);
  146. state_event_ptr state;
  147. for (; (state = try_pop_list(_wait_awakes)) != nullptr;)
  148. {
  149. (void)state->on_notify(this);
  150. }
  151. }
  152. LIBRF_API void event_v2_impl::signal() noexcept
  153. {
  154. scoped_lock<lock_type> lock_(_lock);
  155. state_event_ptr state;
  156. for (; (state = try_pop_list(_wait_awakes)) != nullptr;)
  157. {
  158. if (state->on_notify(this))
  159. return;
  160. }
  161. _counter.fetch_add(1, std::memory_order_acq_rel);
  162. }
  163. LIBRF_API void event_v2_impl::reset() noexcept
  164. {
  165. _counter.store(0, std::memory_order_release);
  166. }
  167. LIBRF_API void event_v2_impl::add_wait_list(state_event_base_t* state)
  168. {
  169. assert(state != nullptr);
  170. _wait_awakes.push_back(state);
  171. }
  172. LIBRF_API void event_v2_impl::remove_wait_list(state_event_base_t* state)
  173. {
  174. assert(state != nullptr);
  175. scoped_lock<lock_type> lock_(_lock);
  176. _wait_awakes.erase(state);
  177. }
  178. }
  179. LIBRF_API event_t::event_t(bool initially)
  180. :_event(std::make_shared<detail::event_v2_impl>(initially))
  181. {
  182. }
  183. LIBRF_API event_t::event_t(std::adopt_lock_t)
  184. {
  185. }
  186. LIBRF_API event_t::~event_t()
  187. {
  188. }
  189. }