BusyWaitableCondition
是忙寻版的可等待条件
WaitableCondition
是睡眠版的可等待条件
两者实现相同功能,只是忙寻版会占用一个cpu core,而睡眠版会陷入睡眠在需要时才被唤醒继续执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| #include <iostream> #include <atomic> #include <mutex> #include <condition_variable> #include <chrono> #include <thread> #include <future>
using namespace std;
class BusyWaitableCondition { public: void Wait() { while(!_flag); }
void Notify() { _flag = true; }
void Reset() { _flag = false; }
private: std::atomic<bool> _flag = false; };
class WaitableCondition { public: void Wait() { std::unique_lock<std::mutex> lock(_mutex); if(!_flag) { _cv.wait(lock, [this](){ return _flag; }); } }
void Notify() { do { std::lock_guard<std::mutex> lock(_mutex); _flag = true; } while(false); _cv.notify_all(); }
void Reset() { std::lock_guard<std::mutex> lock(_mutex); _flag = false; }
private: std::mutex _mutex; std::condition_variable _cv; bool _flag = false; };
int main() { WaitableCondition c1; auto fut1 = std::async(std::launch::async, [&]{ c1.Wait(); cout << "Hello 1" << endl; }); auto fut2 = std::async(std::launch::async, [&]{ c1.Wait(); cout << "Hello 2" << endl; });
this_thread::sleep_for(chrono::seconds(1)); cout << "1" << endl; cout << "2" << endl; cout << "3" << endl; cout << "4" << endl; cout << "5" << endl; c1.Notify();
return 0; }
|
上面的例子中有定义Reset
方法,但是没有演示,它的作用是将条件设置为否,以便可以再次等待,然后可以重新触发。
如果只需要等待一个一次性事件而不需要Reset
方法那么可以用std::promise
+std::future
进行更简单的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class WaitableEvent { public: WaitableEvent(): _fut(_promise.get_future()) {
}
void Wait() const { _fut.wait(); }
void Notify() { _promise.set_value(); }
private: std::promise<void> _promise; std::future<void> _fut; };
|