ConditionVariable.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #pragma once
  2. #include "Time.h"
  3. #include "Lock.h"
  4. #include <cstdint>
  5. #if PLATFORM_FUTEX_NATIVE_SUPPORT
  6. #include "Internal/ConditionVariableData_FutexBased.inl.h"
  7. #else
  8. #include "Internal/ConditionVariableData_SemaphoreBased.inl.h"
  9. #endif
  10. namespace baselib
  11. {
  12. BASELIB_CPP_INTERFACE
  13. {
  14. // Conceptually a condition variable is a queue of threads, associated with a monitor, on which a thread may wait for some condition to become true.
  15. //
  16. // Thus each condition variable c is associated with an assertion Pc. While a thread is waiting on a condition variable, that thread is not considered
  17. // to occupy the monitor, and so other threads may enter the monitor to change the monitor's state. In most types of monitors, these other threads may
  18. // signal the condition variable c to indicate that assertion Pc is true in the current state.
  19. //
  20. // "Monitor (synchronization)", Wikipedia: The Free Encyclopedia
  21. // https://en.wikipedia.org/w/index.php?title=Monitor_(synchronization)&oldid=914426020#Condition_variables_2
  22. //
  23. // For optimal performance, baselib::ConditionVariable should be stored at a cache aligned memory location.
  24. class ConditionVariable
  25. {
  26. public:
  27. // non-copyable
  28. ConditionVariable(const ConditionVariable& other) = delete;
  29. ConditionVariable& operator=(const ConditionVariable& other) = delete;
  30. // non-movable (strictly speaking not needed but listed to signal intent)
  31. ConditionVariable(ConditionVariable&& other) = delete;
  32. ConditionVariable& operator=(ConditionVariable&& other) = delete;
  33. // Creates a condition variable synchronization primitive.
  34. ConditionVariable(Lock& lock) : m_Lock(lock)
  35. {}
  36. // Reclaim resources and memory held by the condition variable.
  37. //
  38. // If threads are waiting on the condition variable, destructor will trigger an assert and may cause process abort.
  39. ~ConditionVariable()
  40. {
  41. BaselibAssert(!m_Data.HasWaiters(), "Destruction is not allowed when there are still threads waiting on the condition variable.");
  42. NotifyAll();
  43. }
  44. // Wait for the condition variable to become available.
  45. //
  46. // The lock must have been previously acquired.
  47. // For the duration of the wait the lock is released and then re-acquired upon exit.
  48. // This function is guaranteed to emit an acquire barrier.
  49. inline void Wait();
  50. // Wait for the condition variable to become available.
  51. //
  52. // The lock must have been previously acquired.
  53. // For the duration of the wait the lock is released and then re-acquired upon exit.
  54. // This function is guaranteed to emit an acquire barrier.
  55. //
  56. // TimedWait with a zero timeout is guaranteed to be a user space operation.
  57. //
  58. // \param timeoutInMilliseconds Time to wait for condition variable to become available.
  59. // \returns true if the condition variable is available, false if timeout was reached.
  60. inline bool TimedWait(const timeout_ms timeoutInMilliseconds);
  61. // Wake up threads waiting for the condition variable.
  62. //
  63. // This function is guaranteed to emit a release barrier.
  64. //
  65. // \param count At most, `count` waiting threads will be notified, but never more than there are currently waiting.
  66. inline void Notify(uint16_t count);
  67. // Wake up all threads waiting for the condition variable.
  68. //
  69. // This function is guaranteed to emit a release barrier.
  70. inline void NotifyAll()
  71. {
  72. Notify(std::numeric_limits<uint16_t>::max());
  73. }
  74. private:
  75. Lock& m_Lock;
  76. detail::ConditionVariableData m_Data;
  77. };
  78. }
  79. }
  80. #if PLATFORM_FUTEX_NATIVE_SUPPORT
  81. #include "Internal/ConditionVariable_FutexBased.inl.h"
  82. #else
  83. #include "Internal/ConditionVariable_SemaphoreBased.inl.h"
  84. #endif