fork download
  1. #include <iostream>
  2. #include <atomic>
  3. #include <thread>
  4. #include <mutex>
  5. #include <condition_variable>
  6. #include <chrono>
  7.  
  8. using namespace std;
  9.  
  10.  
  11. class EventWaitHandle {
  12.  
  13. public:
  14. EventWaitHandle(bool handleWillCloseAfterOneWait, bool openAtStart)
  15. : autoReset(handleWillCloseAfterOneWait), handleOpen(openAtStart)
  16. { }
  17.  
  18. void set() {
  19. {
  20. std::lock_guard<std::mutex> handleOpenLock(handleOpenLocker);
  21. handleOpen = true;
  22. }
  23.  
  24. handleOpenSignal.notify_one();
  25. }
  26.  
  27. void reset() {
  28. {
  29. std::lock_guard<std::mutex> handleOpenLock(handleOpenLocker);
  30. handleOpen = false;
  31. }
  32.  
  33. handleOpenSignal.notify_one();
  34. }
  35.  
  36. bool wait(int millisecondsBeforeTimeout) {
  37. {
  38. std::lock_guard<std::mutex> handleOpenLock(handleOpenLocker);
  39.  
  40. if (handleOpen) {
  41. handleOpen = !autoReset;
  42. return true;
  43. }
  44.  
  45. if (millisecondsBeforeTimeout < 1) // Handle isn't open and we are waiting no time, punt..
  46. return false;
  47.  
  48. }
  49.  
  50. auto start = std::chrono::system_clock::now();
  51. cout << "waiting.." << endl;
  52. std::unique_lock<std::mutex> lockJustForThisWaiter(handleOpenLocker);
  53.  
  54. if(handleOpenSignal.wait_until(lockJustForThisWaiter, start + std::chrono::milliseconds(millisecondsBeforeTimeout)) == std::cv_status::timeout)
  55. return false;
  56.  
  57. auto timeLeftToWaitInEventOfSpuriousness = std::chrono::milliseconds(millisecondsBeforeTimeout) - (std::chrono::system_clock::now() - start);
  58. int millisecondsLeftToWait = 0;
  59. millisecondsLeftToWait = std::chrono::duration_cast<std::chrono::milliseconds>(timeLeftToWaitInEventOfSpuriousness).count();
  60.  
  61. return wait(millisecondsLeftToWait);
  62. }
  63.  
  64. private:
  65.  
  66. bool autoReset;
  67.  
  68. std::condition_variable handleOpenSignal;
  69. std::atomic<bool> handleOpen;
  70. std::mutex handleOpenLocker;
  71. };
  72.  
  73.  
  74. int main() {
  75. EventWaitHandle waitHandle(true, true);
  76.  
  77. bool open;
  78.  
  79. open = waitHandle.wait(100);
  80. if (open)
  81. cout << "open" << endl;
  82. else
  83. cout << "not open" << endl;
  84.  
  85. waitHandle.set();
  86.  
  87. open = waitHandle.wait(100);
  88. if (open)
  89. cout << "open" << endl;
  90. else
  91. cout << "not open" << endl;
  92.  
  93. waitHandle.reset();
  94.  
  95. open = waitHandle.wait(100);
  96. if (open)
  97. cout << "open" << endl;
  98. else
  99. cout << "not open" << endl;
  100.  
  101. return 0;
  102. }
Success #stdin #stdout 0s 3416KB
stdin
Standard input is empty
stdout
open
open
waiting..
not open