SLikeNet  0.1.3
 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 
32 {
33 #ifdef _WIN32
34  eventList=INVALID_HANDLE_VALUE;
35 
36 
37 #else
38  isSignaled=false;
39 #endif
40 }
42 {
43  // Intentionally do not close event, so it doesn't close twice on linux
44 }
45 
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 
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 
102 {
103 #ifdef _WIN32
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
119  isSignaled=true;
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
181  if (isSignaled==true)
182  {
183  isSignaled=false;
185  return;
186  }
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 
243  if (isSignaled==true)
244  {
245  isSignaled=false;
247  return;
248  }
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 
265  isSignaled=false;
267 
268 #endif
269 }