SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SignaledEvent.cpp
Go to the documentation of this file.
1 /*
2 * Original work: Copyright (c) 2014, Oculus VR, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2017, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
16 #include "slikenet/SignaledEvent.h"
17 #include "slikenet/assert.h"
18 #include "slikenet/sleep.h"
19
20 #if defined(__GNUC__)
21 #include <sys/time.h>
22 #include <unistd.h>
23 #endif
24
25 using namespace SLNet;
26
27
28
29
30
31 SignaledEvent::SignaledEvent()
32 {
33 #ifdef _WIN32
34 eventList=INVALID_HANDLE_VALUE;
35
36
37 #else
38 isSignaled=false;
39 #endif
40 }
41 SignaledEvent::~SignaledEvent()
42 {
43 // Intentionally do not close event, so it doesn't close twice on linux
44 }
45
46 void SignaledEvent::InitEvent(void)
47 {
48 #if defined(WINDOWS_PHONE_8) || defined(WINDOWS_STORE_RT)
49 eventList=CreateEventEx(0, 0, 0, 0);
50 #elif defined(_WIN32)
51 eventList=CreateEvent(0, false, false, 0);
52
53
54
55
56
57
58
59
60
61 #else
62
63 #if !defined(ANDROID)
64 pthread_condattr_init( &condAttr );
65 pthread_cond_init(&eventList, &condAttr);
66 #else
67 pthread_cond_init(&eventList, 0);
68 #endif
69 pthread_mutexattr_init( &mutexAttr );
70 pthread_mutex_init(&hMutex, &mutexAttr);
71 #endif
72 }
73
74 void SignaledEvent::CloseEvent(void)
75 {
76 #ifdef _WIN32
77 if (eventList!=INVALID_HANDLE_VALUE)
78 {
79 CloseHandle(eventList);
80 eventList=INVALID_HANDLE_VALUE;
81 }
82
83
84
85
86
87
88
89
90
91 #else
92 pthread_cond_destroy(&eventList);
93 pthread_mutex_destroy(&hMutex);
94 #if !defined(ANDROID)
95 pthread_condattr_destroy( &condAttr );
96 #endif
97 pthread_mutexattr_destroy( &mutexAttr );
98 #endif
99 }
100
101 void SignaledEvent::SetEvent(void)
102 {
103 #ifdef _WIN32
104 ::SetEvent(eventList);
105
106
107
108
109
110
111
112
113
114
115 #else
116 // Different from SetEvent which stays signaled.
117 // We have to record manually that the event was signaled
118 isSignaledMutex.Lock();
119 isSignaled=true;
120 isSignaledMutex.Unlock();
121
122 // Unblock waiting threads
123 pthread_cond_broadcast(&eventList);
124 #endif
125 }
126
127 void SignaledEvent::WaitOnEvent(int timeoutMs)
128 {
129 #ifdef _WIN32
130 // WaitForMultipleObjects(
131 // 2,
132 // eventList,
133 // false,
134 // timeoutMs);
135 WaitForSingleObjectEx(eventList,timeoutMs,FALSE);
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 #else
178
179 // If was previously set signaled, just unset and return
180 isSignaledMutex.Lock();
181 if (isSignaled==true)
182 {
183 isSignaled=false;
184 isSignaledMutex.Unlock();
185 return;
186 }
187 isSignaledMutex.Unlock();
188
189
190
191 //struct timespec ts;
192
193 // Else wait for SetEvent to be called
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211 struct timespec ts;
212
213 int rc;
214 struct timeval tp;
215 rc = gettimeofday(&tp, NULL);
216 ts.tv_sec = tp.tv_sec;
217 ts.tv_nsec = tp.tv_usec * 1000;
218 // #endif
219
220 while (timeoutMs > 30)
221 {
222 // Wait 30 milliseconds for the signal, then check again.
223 // This is in case we missed the signal between the top of this function and pthread_cond_timedwait, or after the end of the loop and pthread_cond_timedwait
224 ts.tv_nsec += 30*1000000;
225 if (ts.tv_nsec >= 1000000000)
226 {
227 ts.tv_nsec -= 1000000000;
228 ts.tv_sec++;
229 }
230
231 // [SBC] added mutex lock/unlock around cond_timedwait.
232 // this prevents airplay from generating a whole much of errors.
233 // not sure how this works on other platforms since according to
234 // the docs you are suppost to hold the lock before you wait
235 // on the cond.
236 pthread_mutex_lock(&hMutex);
237 pthread_cond_timedwait(&eventList, &hMutex, &ts);
238 pthread_mutex_unlock(&hMutex);
239
240 timeoutMs-=30;
241
242 isSignaledMutex.Lock();
243 if (isSignaled==true)
244 {
245 isSignaled=false;
246 isSignaledMutex.Unlock();
247 return;
248 }
249 isSignaledMutex.Unlock();
250 }
251
252 // Wait the remaining time, and turn off the signal in case it was set
253 ts.tv_nsec += timeoutMs*1000000;
254 if (ts.tv_nsec >= 1000000000)
255 {
256 ts.tv_nsec -= 1000000000;
257 ts.tv_sec++;
258 }
259
260 pthread_mutex_lock(&hMutex);
261 pthread_cond_timedwait(&eventList, &hMutex, &ts);
262 pthread_mutex_unlock(&hMutex);
263
264 isSignaledMutex.Lock();
265 isSignaled=false;
266 isSignaledMutex.Unlock();
267
268 #endif
269 }