CppCommon 1.0.5.0
C++ Common Library
Loading...
Searching...
No Matches
named_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__) && !defined(__CYGWIN__)
17#include "system/shared_type.h"
18#include <pthread.h>
19#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
20#include <windows.h>
21#undef max
22#undef min
23#endif
24
25namespace CppCommon {
26
28
29class NamedEventManualReset::Impl
30{
31public:
32 Impl(const std::string& name, bool signaled) : _name(name)
33#if (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__APPLE__) && !defined(__CYGWIN__)
34 , _shared(name)
35#endif
36 {
37#if defined(__APPLE__)
38 throwex SystemException("Named manual-reset event is not supported!");
39#elif (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__CYGWIN__)
40 // Only the owner should initializate a named manual-reset event
41 if (_shared.owner())
42 {
43 pthread_mutexattr_t mutex_attribute;
44 int result = pthread_mutexattr_init(&mutex_attribute);
45 if (result != 0)
46 throwex SystemException("Failed to initialize a mutex attribute for the named manual-reset event!", result);
47 result = pthread_mutexattr_setpshared(&mutex_attribute, PTHREAD_PROCESS_SHARED);
48 if (result != 0)
49 throwex SystemException("Failed to set a mutex process shared attribute for the named manual-reset event!", result);
50 result = pthread_mutex_init(&_shared->mutex, &mutex_attribute);
51 if (result != 0)
52 throwex SystemException("Failed to initialize a mutex for the named manual-reset event!", result);
53 result = pthread_mutexattr_destroy(&mutex_attribute);
54 if (result != 0)
55 throwex SystemException("Failed to destroy a mutex attribute for the named manual-reset event!", result);
56
57 pthread_condattr_t cond_attribute;
58 result = pthread_condattr_init(&cond_attribute);
59 if (result != 0)
60 throwex SystemException("Failed to initialize a conditional variable attribute for the named manual-reset event!", result);
61 result = pthread_condattr_setpshared(&cond_attribute, PTHREAD_PROCESS_SHARED);
62 if (result != 0)
63 throwex SystemException("Failed to set a conditional variable process shared attribute for the named manual-reset event!", result);
64 result = pthread_cond_init(&_shared->cond, &cond_attribute);
65 if (result != 0)
66 throwex SystemException("Failed to initialize a conditional variable for the named manual-reset event!", result);
67 result = pthread_condattr_destroy(&cond_attribute);
68 if (result != 0)
69 throwex SystemException("Failed to destroy a conditional variable attribute for the named manual-reset event!", result);
70
71 _shared->signaled = signaled;
72 }
73#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
74 _event = CreateEventA(nullptr, TRUE, signaled ? TRUE : FALSE, name.c_str());
75 if (_event == nullptr)
76 throwex SystemException("Failed to create or open a named manual-reset event!");
77#endif
78 }
79
80 ~Impl()
81 {
82#if defined(__APPLE__)
83 fatality(SystemException("Named manual-reset event is not supported!"));
84#elif (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__CYGWIN__)
85 // Only the owner should destroy a named manual-reset event
86 if (_shared.owner())
87 {
88 int result = pthread_mutex_destroy(&_shared->mutex);
89 if (result != 0)
90 fatality(SystemException("Failed to destroy a mutex for the named manual-reset event!", result));
91 result = pthread_cond_destroy(&_shared->cond);
92 if (result != 0)
93 fatality(SystemException("Failed to destroy a conditional variable for the named manual-reset event!", result));
94 }
95#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
96 if (!CloseHandle(_event))
97 fatality(SystemException("Failed to close a named manual-reset event!"));
98#endif
99 }
100
101 const std::string& name() const
102 {
103 return _name;
104 }
105
106 void Reset()
107 {
108#if defined(__APPLE__)
109 throwex SystemException("Named manual-reset event is not supported!");
110#elif (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__CYGWIN__)
111 int result = pthread_mutex_lock(&_shared->mutex);
112 if (result != 0)
113 throwex SystemException("Failed to lock a mutex for the named manual-reset event!", result);
114 _shared->signaled = false;
115 result = pthread_mutex_unlock(&_shared->mutex);
116 if (result != 0)
117 throwex SystemException("Failed to unlock a mutex for the named manual-reset event!", result);
118#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
119 if (!ResetEvent(_event))
120 throwex SystemException("Failed to reset a named manual-reset event!");
121#endif
122 }
123
124 void Signal()
125 {
126#if defined(__APPLE__)
127 throwex SystemException("Named manual-reset event is not supported!");
128#elif (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__CYGWIN__)
129 int result = pthread_mutex_lock(&_shared->mutex);
130 if (result != 0)
131 throwex SystemException("Failed to lock a mutex for the named manual-reset event!", result);
132 _shared->signaled = true;
133 result = pthread_mutex_unlock(&_shared->mutex);
134 if (result != 0)
135 throwex SystemException("Failed to unlock a mutex for the named manual-reset event!", result);
136 result = pthread_cond_broadcast(&_shared->cond);
137 if (result != 0)
138 throwex SystemException("Failed to signal an named manual-reset event!", result);
139#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
140 if (!SetEvent(_event))
141 throwex SystemException("Failed to signal a named manual-reset event!");
142#endif
143 }
144
145 bool TryWait()
146 {
147#if defined(__APPLE__)
148 throwex SystemException("Named manual-reset event is not supported!");
149#elif (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__CYGWIN__)
150 int result = pthread_mutex_lock(&_shared->mutex);
151 if (result != 0)
152 throwex SystemException("Failed to lock a mutex for the named manual-reset event!", result);
153 bool signaled = _shared->signaled;
154 result = pthread_mutex_unlock(&_shared->mutex);
155 if (result != 0)
156 throwex SystemException("Failed to unlock a mutex for the named manual-reset event!", result);
157 return signaled;
158#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
159 DWORD result = WaitForSingleObject(_event, 0);
160 if ((result != WAIT_OBJECT_0) && (result != WAIT_TIMEOUT))
161 throwex SystemException("Failed to try lock a named manual-reset event!");
162 return (result == WAIT_OBJECT_0);
163#endif
164 }
165
166 bool TryWaitFor(const Timespan& timespan)
167 {
168 if (timespan < 0)
169 return TryWait();
170#if defined(__APPLE__)
171 throwex SystemException("Named manual-reset event is not supported!");
172#elif (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__CYGWIN__)
173 struct timespec timeout;
174 timeout.tv_sec = timespan.seconds();
175 timeout.tv_nsec = timespan.nanoseconds() % 1000000000;
176 int result = pthread_mutex_lock(&_shared->mutex);
177 if (result != 0)
178 throwex SystemException("Failed to lock a mutex for the named manual-reset event!", result);
179 bool signaled = true;
180 while (!_shared->signaled)
181 {
182 result = pthread_cond_timedwait(&_shared->cond, &_shared->mutex, &timeout);
183 if ((result != 0) && (result != ETIMEDOUT))
184 throwex SystemException("Failed to timeout waiting a conditional variable for the named manual-reset event!", result);
185 if (result == ETIMEDOUT)
186 signaled = _shared->signaled;
187 }
188 result = pthread_mutex_unlock(&_shared->mutex);
189 if (result != 0)
190 throwex SystemException("Failed to unlock a mutex for the named manual-reset event!", result);
191 return signaled;
192#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
193 DWORD result = WaitForSingleObject(_event, std::max((DWORD)1, (DWORD)timespan.milliseconds()));
194 if ((result != WAIT_OBJECT_0) && (result != WAIT_TIMEOUT))
195 throwex SystemException("Failed to try lock a named manual-reset event for the given timeout!");
196 return (result == WAIT_OBJECT_0);
197#endif
198 }
199
200 void Wait()
201 {
202#if defined(__APPLE__)
203 throwex SystemException("Named manual-reset event is not supported!");
204#elif (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__CYGWIN__)
205 int result = pthread_mutex_lock(&_shared->mutex);
206 if (result != 0)
207 throwex SystemException("Failed to lock a mutex for the named manual-reset event!", result);
208 while (!_shared->signaled)
209 {
210 result = pthread_cond_wait(&_shared->cond, &_shared->mutex);
211 if (result != 0)
212 throwex SystemException("Failed to waiting a conditional variable for the named manual-reset event!", result);
213 }
214 result = pthread_mutex_unlock(&_shared->mutex);
215 if (result != 0)
216 throwex SystemException("Failed to unlock a mutex for the named manual-reset event!", result);
217#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
218 DWORD result = WaitForSingleObject(_event, INFINITE);
219 if (result != WAIT_OBJECT_0)
220 throwex SystemException("Failed to lock a named manual-reset event!");
221#endif
222 }
223
224private:
225 std::string _name;
226#if (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__APPLE__) && !defined(__CYGWIN__)
227 // Shared manual-reset event structure
228 struct EventHeader
229 {
230 pthread_mutex_t mutex;
231 pthread_cond_t cond;
232 int signaled;
233 };
234
235 // Shared manual-reset event structure wrapper
236 SharedType<EventHeader> _shared;
237#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
238 HANDLE _event;
239#endif
240};
241
243
244NamedEventManualReset::NamedEventManualReset(const std::string& name, bool signaled)
245{
246 // Check implementation storage parameters
247 [[maybe_unused]] ValidateAlignedStorage<sizeof(Impl), alignof(Impl), StorageSize, StorageAlign> _;
248 static_assert((StorageSize >= sizeof(Impl)), "NamedEventManualReset::StorageSize must be increased!");
249 static_assert(((StorageAlign % alignof(Impl)) == 0), "NamedEventManualReset::StorageAlign must be adjusted!");
250
251 // Create the implementation instance
252 new(&_storage)Impl(name, signaled);
253}
254
256{
257 // Delete the implementation instance
258 reinterpret_cast<Impl*>(&_storage)->~Impl();
259}
260
261const std::string& NamedEventManualReset::name() const { return impl().name(); }
262
263void NamedEventManualReset::Reset() { impl().Reset(); }
264void NamedEventManualReset::Signal() { impl().Signal(); }
265
266bool NamedEventManualReset::TryWait() { return impl().TryWait(); }
267bool NamedEventManualReset::TryWaitFor(const Timespan& timespan) { return impl().TryWaitFor(timespan); }
268
269void NamedEventManualReset::Wait() { impl().Wait(); }
270
271} // namespace CppCommon
void Signal()
Signal one of waiting thread about event occurred.
const std::string & name() const
Get the event name.
void Wait()
Try to wait the event with block.
NamedEventManualReset(const std::string &name, bool signaled=false)
Default class constructor.
bool TryWait()
Try to wait the event without block.
bool TryWaitFor(const Timespan &timespan)
Try to wait the event for the given timespan.
#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
Named manual-reset event synchronization primitive definition.
C++ Common project definitions.
Shared memory type definition.
Aligned storage validator definition.