SyncEvent.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #pragma once
  2. #include <condition_variable>
  3. #include <mutex>
  4. #include <chrono>
  5. //-----------------------------------------------------------------------------
  6. // SyncEvent
  7. //-----------------------------------------------------------------------------
  8. namespace SyncEvent
  9. {
  10. class _Base
  11. {
  12. protected:
  13. bool m_bEvent = false;
  14. std::mutex m_EventMutex;
  15. std::condition_variable m_EventCond;
  16. protected:
  17. _Base ()
  18. {
  19. m_bEvent = false;
  20. }
  21. public:
  22. void Set ()
  23. {
  24. m_bEvent = true;
  25. m_EventCond.notify_all ();
  26. }
  27. void Reset ()
  28. {
  29. m_bEvent = false;
  30. }
  31. void Pulse ()
  32. {
  33. m_bEvent = false;
  34. m_bEvent = true;
  35. m_EventCond.notify_all ();
  36. }
  37. // 用于测试
  38. void _SetOne ()
  39. {
  40. m_bEvent = true;
  41. m_EventCond.notify_one ();
  42. }
  43. };
  44. //-----------------------------------------------------------------------------
  45. // Manual
  46. //-----------------------------------------------------------------------------
  47. class Manual : public _Base
  48. {
  49. public:
  50. using _Base::_Base;
  51. public:
  52. void Wait ()
  53. {
  54. std::unique_lock <std::mutex> lk (m_EventMutex);
  55. m_EventCond.wait (lk, [this] () { return m_bEvent; });
  56. }
  57. // 返回 true : 确实等到了事件通知
  58. // 返回 false: 超时
  59. bool Wait (const std::chrono::milliseconds & dur)
  60. {
  61. std::unique_lock <std::mutex> lk (m_EventMutex);
  62. auto rc = m_EventCond.wait_for (lk, dur, [this] () { return m_bEvent; });
  63. return rc;
  64. }
  65. };
  66. //-----------------------------------------------------------------------------
  67. // Auto
  68. //-----------------------------------------------------------------------------
  69. class Auto : public _Base
  70. {
  71. public:
  72. using _Base::_Base;
  73. public:
  74. void Wait ()
  75. {
  76. std::unique_lock <std::mutex> lk (m_EventMutex);
  77. m_EventCond.wait (lk, [this] ()
  78. {
  79. if (! m_bEvent) return false;
  80. m_bEvent = false;
  81. return true;
  82. });
  83. }
  84. // 返回 true : 确实等到了事件通知
  85. // 返回 false: 超时
  86. bool Wait (const std::chrono::milliseconds & dur)
  87. {
  88. std::unique_lock <std::mutex> lk (m_EventMutex);
  89. auto rc = m_EventCond.wait_for (lk, dur, [this] ()
  90. {
  91. if (! m_bEvent) return false;
  92. m_bEvent = false;
  93. return true;
  94. });
  95. return rc;
  96. }
  97. };
  98. }
  99. /*//-----------------------------------------------------------------------------
  100. Manual 类型:
  101. - 在 Set 之后, 所有的 Wait 线程都得到解锁, 开始执行下一步
  102. - 再次 Wait 之前, 必须手动调用 Reset, 否则 Wait 直接返回 (相当于直接解锁)
  103. Auto 类型:
  104. - 在 Set 之后, 所有 Wait 线程中只有 1 个得到解锁, 开始执行下一步
  105. - 可以随时 Wait, 无需手动调用 Reset
  106. *///-----------------------------------------------------------------------------
  107. /*//-----------------------------------------------------------------------------
  108. 测试代码:
  109. static int THTest (int num)
  110. {
  111. time_t t;
  112. time (& t);
  113. printf ("%d enter at %s", num, ctime (&t));
  114. evt.Wait ();
  115. time (& t);
  116. printf ("%d.1 - at %s ", num, ctime (&t));
  117. evt.Reset ();
  118. evt.Wait ();
  119. time (& t);
  120. printf ("%d.2 - at %s ", num, ctime (&t));
  121. evt.Wait ();
  122. time (& t);
  123. printf ("%d.3 - at %s ", num, ctime (&t));
  124. time (& t);
  125. printf ("%d exit at %s", num, ctime (&t));
  126. return num;
  127. }
  128. static void SyncTest ()
  129. {
  130. std::thread (THTest, 12).detach ();
  131. std::thread (THTest, 34).detach ();
  132. std::thread (THTest, 56).detach ();
  133. std::thread (THTest, 78).detach ();
  134. for (int Index = 0; Index < 20; Index++)
  135. {
  136. // printf ("--> ");
  137. Sleep (1000);
  138. evt.Set ();
  139. }
  140. }
  141. 如果是 SyncEvent::Manual evt, 则输出如下:
  142. 78 enter at 21:30:11 2020
  143. 34 enter at 21:30:11 2020
  144. 56 enter at 21:30:11 2020
  145. 12 enter at 21:30:11 2020
  146. 12.1 - at 21:30:12 2020
  147. 56.1 - at 21:30:12 2020
  148. 34.1 - at 21:30:12 2020
  149. 78.1 - at 21:30:12 2020
  150. 34.2 - at 21:30:13 2020
  151. 34.3 - at 21:30:13 2020
  152. 56.2 - at 21:30:13 2020
  153. 12.2 - at 21:30:13 2020
  154. 78.2 - at 21:30:13 2020
  155. 34 exit at 21:30:13 2020
  156. 56.3 - at 21:30:13 2020
  157. 12.3 - at 21:30:13 2020
  158. 78.3 - at 21:30:13 2020
  159. 78 exit at 21:30:13 2020
  160. 56 exit at 21:30:13 2020
  161. 12 exit at 21:30:13 2020
  162. 如果是 SyncEvent::Auto evt, 则输出如下
  163. 12 enter at 21:41:26 2020
  164. 78 enter at 21:41:26 2020
  165. 56 enter at 21:41:26 2020
  166. 34 enter at 21:41:26 2020
  167. 34.1 - at 21:41:27 2020
  168. 56.1 - at 21:41:28 2020
  169. 12.1 - at 21:41:29 2020
  170. 78.1 - at 21:41:30 2020
  171. 12.2 - at 21:41:31 2020
  172. 78.2 - at 21:41:32 2020
  173. 56.2 - at 21:41:33 2020
  174. 56.3 - at 21:41:34 2020
  175. 56 exit at 21:41:34 2020
  176. 34.2 - at 21:41:35 2020
  177. 12.3 - at 21:41:36 2020
  178. 12 exit at 21:41:36 2020
  179. 78.3 - at 21:41:37 2020
  180. 78 exit at 21:41:37 2020
  181. 34.3 - at 21:41:38 2020
  182. 34 exit at 21:41:38 2020
  183. *///-----------------------------------------------------------------------------