123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- #pragma once
- #include <condition_variable>
- #include <mutex>
- #include <chrono>
- //-----------------------------------------------------------------------------
- // SyncEvent
- //-----------------------------------------------------------------------------
- namespace SyncEvent
- {
- class _Base
- {
- protected:
- bool m_bEvent = false;
- std::mutex m_EventMutex;
- std::condition_variable m_EventCond;
- protected:
- _Base ()
- {
- m_bEvent = false;
- }
- public:
- void Set ()
- {
- m_bEvent = true;
- m_EventCond.notify_all ();
- }
- void Reset ()
- {
- m_bEvent = false;
- }
- void Pulse ()
- {
- m_bEvent = false;
- m_bEvent = true;
- m_EventCond.notify_all ();
- }
- // 用于测试
- void _SetOne ()
- {
- m_bEvent = true;
- m_EventCond.notify_one ();
- }
- };
- //-----------------------------------------------------------------------------
- // Manual
- //-----------------------------------------------------------------------------
- class Manual : public _Base
- {
- public:
- using _Base::_Base;
- public:
- void Wait ()
- {
- std::unique_lock <std::mutex> lk (m_EventMutex);
- m_EventCond.wait (lk, [this] () { return m_bEvent; });
- }
- // 返回 true : 确实等到了事件通知
- // 返回 false: 超时
- bool Wait (const std::chrono::milliseconds & dur)
- {
- std::unique_lock <std::mutex> lk (m_EventMutex);
- auto rc = m_EventCond.wait_for (lk, dur, [this] () { return m_bEvent; });
- return rc;
- }
- };
- //-----------------------------------------------------------------------------
- // Auto
- //-----------------------------------------------------------------------------
- class Auto : public _Base
- {
- public:
- using _Base::_Base;
- public:
- void Wait ()
- {
- std::unique_lock <std::mutex> lk (m_EventMutex);
- m_EventCond.wait (lk, [this] ()
- {
- if (! m_bEvent) return false;
- m_bEvent = false;
- return true;
- });
- }
- // 返回 true : 确实等到了事件通知
- // 返回 false: 超时
- bool Wait (const std::chrono::milliseconds & dur)
- {
- std::unique_lock <std::mutex> lk (m_EventMutex);
- auto rc = m_EventCond.wait_for (lk, dur, [this] ()
- {
- if (! m_bEvent) return false;
- m_bEvent = false;
- return true;
- });
- return rc;
- }
- };
- }
- /*//-----------------------------------------------------------------------------
- Manual 类型:
- - 在 Set 之后, 所有的 Wait 线程都得到解锁, 开始执行下一步
- - 再次 Wait 之前, 必须手动调用 Reset, 否则 Wait 直接返回 (相当于直接解锁)
- Auto 类型:
- - 在 Set 之后, 所有 Wait 线程中只有 1 个得到解锁, 开始执行下一步
- - 可以随时 Wait, 无需手动调用 Reset
- *///-----------------------------------------------------------------------------
- /*//-----------------------------------------------------------------------------
- 测试代码:
- static int THTest (int num)
- {
- time_t t;
- time (& t);
- printf ("%d enter at %s", num, ctime (&t));
- evt.Wait ();
- time (& t);
- printf ("%d.1 - at %s ", num, ctime (&t));
- evt.Reset ();
- evt.Wait ();
- time (& t);
- printf ("%d.2 - at %s ", num, ctime (&t));
- evt.Wait ();
- time (& t);
- printf ("%d.3 - at %s ", num, ctime (&t));
- time (& t);
- printf ("%d exit at %s", num, ctime (&t));
- return num;
- }
- static void SyncTest ()
- {
- std::thread (THTest, 12).detach ();
- std::thread (THTest, 34).detach ();
- std::thread (THTest, 56).detach ();
- std::thread (THTest, 78).detach ();
- for (int Index = 0; Index < 20; Index++)
- {
- // printf ("--> ");
- Sleep (1000);
- evt.Set ();
- }
- }
- 如果是 SyncEvent::Manual evt, 则输出如下:
- 78 enter at 21:30:11 2020
- 34 enter at 21:30:11 2020
- 56 enter at 21:30:11 2020
- 12 enter at 21:30:11 2020
- 12.1 - at 21:30:12 2020
- 56.1 - at 21:30:12 2020
- 34.1 - at 21:30:12 2020
- 78.1 - at 21:30:12 2020
- 34.2 - at 21:30:13 2020
- 34.3 - at 21:30:13 2020
- 56.2 - at 21:30:13 2020
- 12.2 - at 21:30:13 2020
- 78.2 - at 21:30:13 2020
- 34 exit at 21:30:13 2020
- 56.3 - at 21:30:13 2020
- 12.3 - at 21:30:13 2020
- 78.3 - at 21:30:13 2020
- 78 exit at 21:30:13 2020
- 56 exit at 21:30:13 2020
- 12 exit at 21:30:13 2020
- 如果是 SyncEvent::Auto evt, 则输出如下
- 12 enter at 21:41:26 2020
- 78 enter at 21:41:26 2020
- 56 enter at 21:41:26 2020
- 34 enter at 21:41:26 2020
- 34.1 - at 21:41:27 2020
- 56.1 - at 21:41:28 2020
- 12.1 - at 21:41:29 2020
- 78.1 - at 21:41:30 2020
- 12.2 - at 21:41:31 2020
- 78.2 - at 21:41:32 2020
- 56.2 - at 21:41:33 2020
- 56.3 - at 21:41:34 2020
- 56 exit at 21:41:34 2020
- 34.2 - at 21:41:35 2020
- 12.3 - at 21:41:36 2020
- 12 exit at 21:41:36 2020
- 78.3 - at 21:41:37 2020
- 78 exit at 21:41:37 2020
- 34.3 - at 21:41:38 2020
- 34 exit at 21:41:38 2020
- *///-----------------------------------------------------------------------------
|