libusbemu_threads_win32.h
Go to the documentation of this file.
1 /*
2 * This file is part of the OpenKinect Project. http://www.openkinect.org
3 *
4 * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file
5 * for details.
6 *
7 * This code is licensed to you under the terms of the Apache License, version
8 * 2.0, or, at your option, the terms of the GNU General Public License,
9 * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
10 * or the following URLs:
11 * http://www.apache.org/licenses/LICENSE-2.0
12 * http://www.gnu.org/licenses/gpl-2.0.txt
13 *
14 * If you redistribute this file in source form, modified or unmodified, you
15 * may:
16 * 1) Leave this header intact and distribute it under the same terms,
17 * accompanying it with the APACHE20 and GPL20 files, or
18 * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
19 * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file
20 * In all cases you must keep the copyright notice intact and include a copy
21 * of the CONTRIB file.
22 *
23 * Binary distributions must follow the binary distribution requirements of
24 * either License.
25 */
26 
27 #pragma once
28 
29 #include <windows.h>
30 #include <stdio.h>
31 #include <vector>
32 #include <algorithm>
33 
34 namespace libusbemu {
35 
36 struct QuickEvent
37 {
38 friend struct EventList;
39 
40 private:
41  HANDLE hEvent;
42 
43 public:
44  inline QuickEvent(const bool signaled=false) : hEvent(NULL)
45  {
46  hEvent = CreateEvent(NULL, TRUE, (BOOL)signaled, NULL);
47  }
48  inline ~QuickEvent()
49  {
50  CloseHandle(hEvent);
51  }
52  inline void Signal()
53  {
54  SetEvent(hEvent);
55  }
56  inline void Reset()
57  {
58  ResetEvent(hEvent);
59  }
60  inline bool Check()
61  {
62  return(WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 0));
63  }
64  inline const bool WaitUntilTimeout(const unsigned int milliseconds)
65  {
66  return(WAIT_OBJECT_0 == WaitForSingleObject(hEvent, (DWORD)milliseconds));
67  }
68  inline void Wait()
69  {
70  WaitUntilTimeout(INFINITE);
71  }
72 };
73 
74 
75 
77 {
78 private:
79  HANDLE hThread;
80 
81  // Type-safe wrapper that converts arbitrary function signatures into the
82  // required signature of Win32 Thread Procedures (LPTHREAD_START_ROUTINE).
83  // Any Win32 LPTHREAD_START_ROUTINE declared routine can be wrapped as well.
84  // The wrapper is also capable of cleaning up itself upon thread termination.
85  // This wrapper can be extended in the future to support member-functions
86  // to run as thread procedures.
87  template<typename F>
89  {
90  struct State
91  {
92  F* routine;
93  void* params;
94  bool release;
97  };
98  static DWORD WINAPI Thunk(LPVOID lpParameter)
99  {
100  State state = *((State*)lpParameter); // clone state (no heap alloc!)
101  state.sigclone->Signal(); // done cloning, signal back to creator
102  state.sigclone = NULL;
103 
104  // start wrapped thread procedure
105  DWORD ret = (DWORD)state.routine(state.params);
106 
107  // release the associated QuickThread instance if requested
108  if (state.release)
109  delete(state.instance);
110 
111  return(ret);
112  }
113  };
114 
115  // allow the creation of pseudo-handles to the calling thread
116  // this constructor cannot and should never be called explicitly!
117  // use QuickThread::Myself() to spawn a pseudo-handle QuickThread
118  inline QuickThread() : hThread(GetCurrentThread()) {}
119 
120 public:
121  template<typename F>
122  inline QuickThread(F* proc, void* params, const bool auto_release=false) : hThread(NULL)
123  {
124  // the 'typename' is required here because of dependent names...
125  // MSVC relaxes this constraint, but it goes against the standard.
127  state.routine = proc;
128  state.params = params;
129  state.release = auto_release;
130  state.instance = this;
131  // in order to prevent heap allocation, an event is created so that the
132  // thunk function can signal back when it is done cloning the state; this
133  // may look like unnecessary overhead, but the less heap memory control,
134  // the better becomes the management and maintenance of this class.
135  QuickEvent hWaitThunkCloneState;
136  state.sigclone = &hWaitThunkCloneState;
137 
138  // Ready to issue the thread creation:
139  hThread = CreateThread(NULL, 0, &ThreadWrapper<F>::Thunk, (LPVOID)&state, 0, NULL);
140 
141  // Wait for the thread thunk to clone the state...
142  hWaitThunkCloneState.Wait();
143  // Event object will then be automatically released upon return
144  }
145 
146  inline ~QuickThread()
147  {
148  // only if not a pseudo-handle...
149  if (hThread == GetCurrentThread())
150  return;
151  CloseHandle(hThread);
152  }
153 
154  static inline QuickThread Myself()
155  {
156  return(QuickThread());
157  }
158 
159  inline void Join()
160  {
161  WaitForSingleObject(hThread, INFINITE);
162  }
163 
164  inline bool TryJoin()
165  {
166  return(WAIT_OBJECT_0 == WaitForSingleObject(hThread, 0));
167  }
168 
169  inline bool LowerPriority()
170  {
171  return(TRUE == SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL));
172  }
173 
174  inline bool RaisePriority()
175  {
176  return(TRUE == SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL));
177  }
178 
179  static inline void Sleep(int milliseconds)
180  {
181  ::Sleep(milliseconds);
182  }
183 
184 // Yield is already a Win32 macro (WinBase.h)...
185 // http://winapi.freetechsecrets.com/win32/WIN32Yield.htm
186 #ifdef Yield
187 #undef Yield
188 #endif
189 // A pragma push/pop could be used instead, but it does not solve the issues
190 // http://stackoverflow.com/questions/1793800/can-i-redefine-a-c-macro-for-a-few-includes-and-then-define-it-back
191 //#pragma push_macro("Yield")
192 //#undef Yield
193  static inline void Yield()
194  {
195  // Sleep(0) or Sleep(1) ?!
196  // http://stackoverflow.com/questions/1413630/switchtothread-thread-yield-vs-thread-sleep0-vs-thead-sleep1
197  ::Sleep(1);
198  // could also use the following (but the semantics are quite shady...):
199  // http://msdn.microsoft.com/en-us/library/ms686352(v=vs.85).aspx
200  // SwitchToThread();
201  }
202 //#pragma pop_macro("Yield")
203 };
204 
205 
206 
208 {
209 private:
210  CRITICAL_SECTION cs;
211 
212 public:
213  inline QuickMutex()
214  {
215  InitializeCriticalSection(&cs);
216  }
217 
218  inline ~QuickMutex()
219  {
220  DeleteCriticalSection(&cs);
221  }
222 
223  inline const bool TryEnter()
224  {
225  return(0 != TryEnterCriticalSection(&cs));
226  }
227 
228  inline void Enter()
229  {
230  EnterCriticalSection(&cs);
231  }
232 
233  inline void Leave()
234  {
235  LeaveCriticalSection(&cs);
236  }
237 };
238 
239 
240 
241 struct EventList
242 {
244  std::vector<QuickEvent*> m_vEvents;
245  std::vector<HANDLE> m_vHandles;
246 
247  EventList() {};
249 
250  const bool AttachEvent(QuickEvent* poEvent)
251  {
252  mutex.Enter();
253  m_vEvents.push_back(poEvent);
254  m_vHandles.push_back(poEvent->hEvent);
255  mutex.Leave();
256  return(true);
257  }
258 
259  const bool DetachEvent(QuickEvent* poEvent)
260  {
261  mutex.Enter();
262  std::vector<QuickEvent*>::iterator it1 = std::find(m_vEvents.begin(), m_vEvents.end(), poEvent);
263  m_vEvents.erase(it1);
264  std::vector<HANDLE>::iterator it2 = std::find(m_vHandles.begin(), m_vHandles.end(), poEvent->hEvent);
265  m_vHandles.erase(it2);
266  mutex.Leave();
267  return(true);
268  }
269 
270  int WaitAnyUntilTimeout(const unsigned int milliseconds)
271  {
272  int index (-1);
273  mutex.Enter();
274  DWORD ret (WAIT_FAILED);
275  const unsigned int nHandles (m_vHandles.size());
276  if (nHandles > 0)
277  ret = WaitForMultipleObjects(nHandles, &m_vHandles[0], FALSE, milliseconds);
278  if (ret - WAIT_OBJECT_0 < nHandles)
279  index = (int)(ret - WAIT_OBJECT_0);
280  mutex.Leave();
281  return(index);
282  }
283 
284  int WaitAny()
285  {
286  return(WaitAnyUntilTimeout(INFINITE));
287  }
288 
289  int CheckAny()
290  {
291  return(WaitAnyUntilTimeout(0));
292  }
293 
294  const bool WaitAllUntilTimeout(const unsigned int milliseconds)
295  {
296  bool waited (false);
297  mutex.Enter();
298  const unsigned int nHandles (m_vHandles.size());
299  if (nHandles > 0)
300  waited = (WAIT_TIMEOUT != WaitForMultipleObjects(nHandles, &m_vHandles[0], FALSE, milliseconds));
301  mutex.Leave();
302  return(waited);
303  }
304 
305  const bool WaitAll()
306  {
307  return(WaitAllUntilTimeout(INFINITE));
308  }
309 
310  QuickEvent* operator [] (const unsigned int index)
311  {
312  QuickEvent* poEvent (NULL);
313  mutex.Enter();
314  poEvent = m_vEvents[index];
315  mutex.Leave();
316  return(poEvent);
317  }
318 
319 };
320 
321 } //end of 'namespace libusbemu'
int WaitAnyUntilTimeout(const unsigned int milliseconds)
static DWORD WINAPI Thunk(LPVOID lpParameter)
std::vector< QuickEvent * > m_vEvents
QuickEvent(const bool signaled=false)
#define FALSE
Definition: OniCTypes.h:34
const bool WaitUntilTimeout(const unsigned int milliseconds)
const bool AttachEvent(QuickEvent *poEvent)
#define TRUE
Definition: OniCTypes.h:31
const bool WaitAllUntilTimeout(const unsigned int milliseconds)
std::vector< HANDLE > m_vHandles
QuickThread(F *proc, void *params, const bool auto_release=false)
static void Sleep(int milliseconds)
capture state
Definition: micview.c:53
const bool DetachEvent(QuickEvent *poEvent)


libfreenect
Author(s): Hector Martin, Josh Blake, Kyle Machulis, OpenKinect community
autogenerated on Mon Jun 10 2019 13:46:42