CppCommon  1.0.4.1
C++ Common Library
event_manual_reset.cpp
Go to the documentation of this file.
1 
10 
11 #include "errors/fatal.h"
13 
14 #include <algorithm>
15 
16 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
17 #include <pthread.h>
18 #elif defined(_WIN32) || defined(_WIN64)
19 #include <windows.h>
20 #undef max
21 #undef min
22 #endif
23 
24 namespace CppCommon {
25 
27 
28 class EventManualReset::Impl
29 {
30 public:
31  Impl(bool signaled)
32  {
33 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
34  int result = pthread_mutex_init(&_mutex, nullptr);
35  if (result != 0)
36  throwex SystemException("Failed to initialize a mutex for the manual-reset event!", result);
37  result = pthread_cond_init(&_cond, nullptr);
38  if (result != 0)
39  throwex SystemException("Failed to initialize a conditional variable for the manual-reset event!", result);
40  _signaled = signaled;
41 #elif defined(_WIN32) || defined(_WIN64)
42  _event = CreateEvent(nullptr, TRUE, signaled ? TRUE : FALSE, nullptr);
43  if (_event == nullptr)
44  throwex SystemException("Failed to create a manual-reset event!");
45 #endif
46  }
47 
48  ~Impl()
49  {
50 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
51  int result = pthread_mutex_destroy(&_mutex);
52  if (result != 0)
53  fatality(SystemException("Failed to destroy a mutex for the manual-reset event!", result));
54  result = pthread_cond_destroy(&_cond);
55  if (result != 0)
56  fatality(SystemException("Failed to destroy a conditional variable for the manual-reset event!", result));
57 #elif defined(_WIN32) || defined(_WIN64)
58  if (!CloseHandle(_event))
59  fatality(SystemException("Failed to close a manual-reset event!"));
60 #endif
61  }
62 
63  void Reset()
64  {
65 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
66  int result = pthread_mutex_lock(&_mutex);
67  if (result != 0)
68  throwex SystemException("Failed to lock a mutex for the manual-reset event!", result);
69  _signaled = false;
70  result = pthread_mutex_unlock(&_mutex);
71  if (result != 0)
72  throwex SystemException("Failed to unlock a mutex for the manual-reset event!", result);
73 #elif defined(_WIN32) || defined(_WIN64)
74  if (!ResetEvent(_event))
75  throwex SystemException("Failed to reset a manual-reset event!");
76 #endif
77  }
78 
79  void Signal()
80  {
81 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
82  int result = pthread_mutex_lock(&_mutex);
83  if (result != 0)
84  throwex SystemException("Failed to lock a mutex for the manual-reset event!", result);
85  _signaled = true;
86  result = pthread_mutex_unlock(&_mutex);
87  if (result != 0)
88  throwex SystemException("Failed to unlock a mutex for the manual-reset event!", result);
89  result = pthread_cond_broadcast(&_cond);
90  if (result != 0)
91  throwex SystemException("Failed to signal an manual-reset event!", result);
92 #elif defined(_WIN32) || defined(_WIN64)
93  if (!SetEvent(_event))
94  throwex SystemException("Failed to signal a manual-reset event!");
95 #endif
96  }
97 
98  bool TryWait()
99  {
100 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
101  int result = pthread_mutex_lock(&_mutex);
102  if (result != 0)
103  throwex SystemException("Failed to lock a mutex for the manual-reset event!", result);
104  bool signaled = _signaled;
105  result = pthread_mutex_unlock(&_mutex);
106  if (result != 0)
107  throwex SystemException("Failed to unlock a mutex for the manual-reset event!", result);
108  return signaled;
109 #elif defined(_WIN32) || defined(_WIN64)
110  DWORD result = WaitForSingleObject(_event, 0);
111  if ((result != WAIT_OBJECT_0) && (result != WAIT_TIMEOUT))
112  throwex SystemException("Failed to try lock a manual-reset event!");
113  return (result == WAIT_OBJECT_0);
114 #endif
115  }
116 
117  bool TryWaitFor(const Timespan& timespan)
118  {
119  if (timespan < 0)
120  return TryWait();
121 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
122  struct timespec timeout;
123  timeout.tv_sec = timespan.seconds();
124  timeout.tv_nsec = timespan.nanoseconds() % 1000000000;
125  int result = pthread_mutex_lock(&_mutex);
126  if (result != 0)
127  throwex SystemException("Failed to lock a mutex for the manual-reset event!", result);
128  bool signaled = true;
129  while (!_signaled)
130  {
131  result = pthread_cond_timedwait(&_cond, &_mutex, &timeout);
132  if ((result != 0) && (result != ETIMEDOUT))
133  throwex SystemException("Failed to timeout waiting a conditional variable for the manual-reset event!", result);
134  if (result == ETIMEDOUT)
135  signaled = _signaled;
136  }
137  result = pthread_mutex_unlock(&_mutex);
138  if (result != 0)
139  throwex SystemException("Failed to unlock a mutex for the manual-reset event!", result);
140  return signaled;
141 #elif defined(_WIN32) || defined(_WIN64)
142  DWORD result = WaitForSingleObject(_event, std::max((DWORD)1, (DWORD)timespan.milliseconds()));
143  if ((result != WAIT_OBJECT_0) && (result != WAIT_TIMEOUT))
144  throwex SystemException("Failed to try lock a manual-reset event for the given timeout!");
145  return (result == WAIT_OBJECT_0);
146 #endif
147  }
148 
149  void Wait()
150  {
151 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
152  int result = pthread_mutex_lock(&_mutex);
153  if (result != 0)
154  throwex SystemException("Failed to lock a mutex for the manual-reset event!", result);
155  while (!_signaled)
156  {
157  result = pthread_cond_wait(&_cond, &_mutex);
158  if (result != 0)
159  throwex SystemException("Failed to waiting a conditional variable for the manual-reset event!", result);
160  }
161  result = pthread_mutex_unlock(&_mutex);
162  if (result != 0)
163  throwex SystemException("Failed to unlock a mutex for the manual-reset event!", result);
164 #elif defined(_WIN32) || defined(_WIN64)
165  DWORD result = WaitForSingleObject(_event, INFINITE);
166  if (result != WAIT_OBJECT_0)
167  throwex SystemException("Failed to lock a manual-reset event!");
168 #endif
169  }
170 
171 private:
172 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
173  pthread_mutex_t _mutex;
174  pthread_cond_t _cond;
175  bool _signaled;
176 #elif defined(_WIN32) || defined(_WIN64)
177  HANDLE _event;
178 #endif
179 };
180 
182 
184 {
185  // Check implementation storage parameters
186  [[maybe_unused]] ValidateAlignedStorage<sizeof(Impl), alignof(Impl), StorageSize, StorageAlign> _;
187  static_assert((StorageSize >= sizeof(Impl)), "EventManualReset::StorageSize must be increased!");
188  static_assert(((StorageAlign % alignof(Impl)) == 0), "EventManualReset::StorageAlign must be adjusted!");
189 
190  // Create the implementation instance
191  new(&_storage)Impl(signaled);
192 }
193 
195 {
196  // Delete the implementation instance
197  reinterpret_cast<Impl*>(&_storage)->~Impl();
198 }
199 
200 void EventManualReset::Reset() { impl().Reset(); }
201 void EventManualReset::Signal() { impl().Signal(); }
202 
203 bool EventManualReset::TryWait() { return impl().TryWait(); }
204 bool EventManualReset::TryWaitFor(const Timespan& timespan) { return impl().TryWaitFor(timespan); }
205 
206 void EventManualReset::Wait() { impl().Wait(); }
207 
208 } // namespace CppCommon
bool TryWait()
Try to wait the event without block.
void Reset()
Reset the event.
bool TryWaitFor(const Timespan &timespan)
Try to wait the event for the given timespan.
EventManualReset(bool signaled=false)
Default class constructor.
void Wait()
Try to wait the event with block.
void Signal()
Signal one of waiting thread about event occurred.
#define throwex
Throw extended exception macro.
Definition: exceptions.h:23
Manual-reset event synchronization primitive definition.
Fatal abort execution definition.
#define fatality(...)
Fatal abort execution extended macro.
Definition: fatal.h:22
C++ Common project definitions.
Definition: token_bucket.h:15
Aligned storage validator definition.