CppCommon 1.0.5.0
C++ Common Library
Loading...
Searching...
No Matches
condition_variable.cpp
Go to the documentation of this file.
1
10
12
13#include <algorithm>
14
15#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
16#include "errors/fatal.h"
17#include <pthread.h>
18#elif defined(_WIN32) || defined(_WIN64)
19#include <windows.h>
20#undef max
21#undef min
22#endif
23
24namespace CppCommon {
25
27
28class ConditionVariable::Impl
29{
30public:
31 Impl()
32 {
33#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
34 int result = pthread_cond_init(&_cond, nullptr);
35 if (result != 0)
36 throwex SystemException("Failed to initialize a condition variable!", result);
37#elif defined(_WIN32) || defined(_WIN64)
38 InitializeConditionVariable(&_cond);
39#endif
40 }
41
42 ~Impl()
43 {
44#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
45 int result = pthread_cond_destroy(&_cond);
46 if (result != 0)
47 fatality(SystemException("Failed to destroy a condition variable!", result));
48#elif defined(_WIN32) || defined(_WIN64)
49 // Condition variables do not need to be explicitly destroyed.
50#endif
51 }
52
53 void NotifyOne()
54 {
55#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
56 int result = pthread_cond_signal(&_cond);
57 if (result != 0)
58 throwex SystemException("Failed to signal a condition variable!", result);
59#elif defined(_WIN32) || defined(_WIN64)
60 WakeConditionVariable(&_cond);
61#endif
62 }
63
64 void NotifyAll()
65 {
66#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
67 int result = pthread_cond_broadcast(&_cond);
68 if (result != 0)
69 throwex SystemException("Failed to broadcast a condition variable!", result);
70#elif defined(_WIN32) || defined(_WIN64)
71 WakeAllConditionVariable(&_cond);
72#endif
73 }
74
75 void Wait(CriticalSection& cs)
76 {
77#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
78 int result = pthread_cond_wait(&_cond, (pthread_mutex_t*)cs.native());
79 if (result != 0)
80 throwex SystemException("Failed to waiting a condition variable!", result);
81#elif defined(_WIN32) || defined(_WIN64)
82 if (!SleepConditionVariableCS(&_cond, (CRITICAL_SECTION*)cs.native(), INFINITE))
83 throwex SystemException("Failed to waiting a condition variable!");
84#endif
85 }
86
87 bool TryWaitFor(CriticalSection& cs, const Timespan& timespan)
88 {
89 if (timespan < 0)
90 return false;
91#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
92 struct timespec timeout;
93 timeout.tv_sec = timespan.seconds();
94 timeout.tv_nsec = timespan.nanoseconds() % 1000000000;
95 int result = pthread_cond_timedwait(&_cond, (pthread_mutex_t*)cs.native(), &timeout);
96 if ((result != 0) && (result != ETIMEDOUT))
97 throwex SystemException("Failed to waiting a condition variable for the given timeout!", result);
98 return (result == 0);
99#elif defined(_WIN32) || defined(_WIN64)
100 if (!SleepConditionVariableCS(&_cond, (CRITICAL_SECTION*)cs.native(), std::max((DWORD)0, (DWORD)timespan.milliseconds())))
101 {
102 if (GetLastError() != ERROR_TIMEOUT)
103 throwex SystemException("Failed to waiting a condition variable for the given timeout!");
104 return false;
105 }
106 return true;
107#endif
108 }
109
110private:
111#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
112 pthread_cond_t _cond;
113#elif defined(_WIN32) || defined(_WIN64)
114 CONDITION_VARIABLE _cond;
115#endif
116};
117
119
121{
122 // Check implementation storage parameters
123 [[maybe_unused]] ValidateAlignedStorage<sizeof(Impl), alignof(Impl), StorageSize, StorageAlign> _;
124 static_assert((StorageSize >= sizeof(Impl)), "ConditionVariable::StorageSize must be increased!");
125 static_assert(((StorageAlign % alignof(Impl)) == 0), "ConditionVariable::StorageAlign must be adjusted!");
126
127 // Create the implementation instance
128 new(&_storage)Impl();
129}
130
132{
133 // Delete the implementation instance
134 reinterpret_cast<Impl*>(&_storage)->~Impl();
135}
136
137void ConditionVariable::NotifyOne() { impl().NotifyOne(); }
138void ConditionVariable::NotifyAll() { impl().NotifyAll(); }
139
140void ConditionVariable::Wait(CriticalSection& cs) { impl().Wait(cs); }
141
142bool ConditionVariable::TryWaitFor(CriticalSection& cs, const Timespan& timespan) { return impl().TryWaitFor(cs, timespan); }
143
144} // namespace CppCommon
bool TryWaitFor(CriticalSection &cs, const Timespan &timespan)
Try to wait for the given timespan until condition variable is notified.
void Wait(CriticalSection &cs)
Wait until condition variable is notified.
void NotifyOne()
Notify one of waiting thread about event occurred.
void NotifyAll()
Notify all waiting threads about event occurred.
Critical section synchronization primitive.
Condition variable synchronization primitive definition.
#define throwex
Throw extended exception macro.
Definition exceptions.h:23
Fatal abort execution definition.
#define fatality(...)
Fatal abort execution extended macro.
Definition fatal.h:22
C++ Common project definitions.
Aligned storage validator definition.