#pragma once #include #include #include //----------------------------------------------------------------------------- // 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 lk (m_EventMutex); m_EventCond.wait (lk, [this] () { return m_bEvent; }); } // 返回 true : 确实等到了事件通知 // 返回 false: 超时 bool Wait (const std::chrono::milliseconds & dur) { std::unique_lock 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 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 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 *///-----------------------------------------------------------------------------