waitable_event.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Windows-like event sync object
  2. //
  3. // ISO C++ 98 - POSIX / ISO C++ 11
  4. // $Id$
  5. //
  6. // (c) __vic 2011
  7. #ifndef __VIC_WAITABLE_EVENT_H
  8. #define __VIC_WAITABLE_EVENT_H
  9. #include<__vic/defs.h>
  10. #if __cplusplus >= 201103L // C++11
  11. #include<mutex>
  12. #include<condition_variable>
  13. #include<atomic>
  14. #include<chrono>
  15. #else // C++98
  16. #include<__vic/posix/mutex.h>
  17. #include<__vic/posix/cond_variable.h>
  18. #endif
  19. namespace __vic {
  20. //////////////////////////////////////////////////////////////////////////////
  21. class waitable_event
  22. {
  23. #if __cplusplus >= 201103L // C++11
  24. std::mutex mtx;
  25. std::condition_variable cond;
  26. class atomic_bool
  27. {
  28. std::atomic<bool> v;
  29. public:
  30. explicit atomic_bool(bool val) : v(val) {}
  31. void operator=(bool val) { v.store(val, std::memory_order_release); }
  32. bool load() const { return v.load(std::memory_order_acquire); }
  33. } signaled_;
  34. #else // C++98
  35. posix::mutex mtx;
  36. posix::cond_variable cond;
  37. bool signaled_;
  38. #endif
  39. public:
  40. explicit waitable_event(bool = false);
  41. ~waitable_event();
  42. void set();
  43. void reset(); // clear the signaled state
  44. bool signaled() const;
  45. void wait();
  46. bool wait_ms(unsigned );
  47. #if __cplusplus >= 201103L // C++11
  48. template<class Rep, class Period>
  49. bool wait_for(const std::chrono::duration<Rep,Period> & );
  50. template<class Clock, class Duration>
  51. bool wait_until(const std::chrono::time_point<Clock,Duration> & );
  52. #endif
  53. };
  54. //////////////////////////////////////////////////////////////////////////////
  55. #if __cplusplus >= 201103L // C++11
  56. //----------------------------------------------------------------------------
  57. inline bool waitable_event::signaled() const
  58. {
  59. return signaled_.load();
  60. }
  61. //----------------------------------------------------------------------------
  62. inline void waitable_event::reset()
  63. {
  64. signaled_ = false;
  65. }
  66. //----------------------------------------------------------------------------
  67. template<class R, class P>
  68. bool waitable_event::wait_for(const std::chrono::duration<R,P> &t)
  69. {
  70. if(signaled()) return true;
  71. std::unique_lock<std::mutex> lock(mtx);
  72. auto &s = signaled_;
  73. return cond.wait_for(lock, t, [&s]{ return s.load(); });
  74. }
  75. //----------------------------------------------------------------------------
  76. template<class C, class D>
  77. bool waitable_event::wait_until(const std::chrono::time_point<C,D> &t)
  78. {
  79. if(signaled()) return true;
  80. std::unique_lock<std::mutex> lock(mtx);
  81. auto &s = signaled_;
  82. return cond.wait_until(lock, t, [&s]{ return s.load(); });
  83. }
  84. //----------------------------------------------------------------------------
  85. inline bool waitable_event::wait_ms(unsigned msec)
  86. {
  87. return wait_for(std::chrono::milliseconds(msec));
  88. }
  89. //----------------------------------------------------------------------------
  90. #endif
  91. } // namespace
  92. #endif // header guard