CppCommon 1.0.5.0
C++ Common Library
Loading...
Searching...
No Matches
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
24namespace CppCommon {
25
27
28class EventManualReset::Impl
29{
30public:
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
171private:
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
200void EventManualReset::Reset() { impl().Reset(); }
201void EventManualReset::Signal() { impl().Signal(); }
202
203bool EventManualReset::TryWait() { return impl().TryWait(); }
204bool EventManualReset::TryWaitFor(const Timespan& timespan) { return impl().TryWaitFor(timespan); }
205
206void EventManualReset::Wait() { impl().Wait(); }
207
208} // namespace CppCommon
bool TryWait()
Try to wait the event without block.
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.
Aligned storage validator definition.