RTAB-Map 0.23.10
Real-Time Appearance-Based Mapping
Loading...
Searching...
No Matches
UThreadC.h
1
2// Written by Phillip Sitbon
3// Copyright 2003
4//
5// Modified by Mathieu Labbe
6//
7// Win32/Thread.h
8// - Windows thread
9//
10// - From CreateThread Platform SDK Documentation:
11//
12// "A thread that uses functions from the static C run-time
13// libraries should use the beginthread and endthread C run-time
14// functions for thread management rather than CreateThread and
15// ExitThread. Failure to do so results in small memory leaks
16// when ExitThread is called. Note that this is not a problem
17// with the C run-time in a DLL."
18//
19// With regards to this, I have decided to use the CreateThread
20// API, unless you define _CRT_ in which case there are two
21// possibilities:
22//
23// 1. Define _USE_BEGINTHREAD: Uses _beginthread/_endthread
24// (said to be *unreliable* in the SDK docs)
25//
26// 2. Don't - Uses _beginthreaded/_endthreadex
27//
28// A note about _endthread:
29//
30// It will call CloseHandle() on exit, and if it was already
31// closed then you will get an exception. To prevent this, I
32// removed the CloseHandle() functionality - this means that
33// a Join() WILL wait on a Detach()'ed thread.
34//
36#ifndef _U_Thread_Win32_
37#define _U_Thread_Win32_
38
39#include "rtabmap/utilite/utilite_export.h"
40#include "rtabmap/utilite/Win32/UWin32.h"
41#include "rtabmap/utilite/USemaphore.h"
42#include "rtabmap/utilite/UMutex.h"
43
44inline void uSleep(unsigned int ms)
45{
46 Sleep(ms);
47}
48
49#ifdef _CRT_
50# include <process.h>
51# ifdef _USE_BEGINTHREAD
52# define THREAD_CALL __cdecl
53# define THREAD_HANDLE uintptr_t
54# define THREAD_RET_T void
55# define CREATE_THREAD_FAILED (-1L)
56# define CREATE_THREAD_ERROR (errno)
57# define CREATE_THREAD(_S,_F,_P) ((Handle)_beginthread((void (__cdecl *)(void *))_F,_S,(void *)_P))
58# define EXIT_THREAD _endthread()
59# define CLOSE_HANDLE(x) 1
60# define THREAD_RETURN(x) return
61# else
62# define THREAD_CALL WINAPI
63# define THREAD_HANDLE HANDLE
64# define THREAD_RET_T UINT
65# define CREATE_THREAD_FAILED (0L)
66# define CREATE_THREAD_ERROR (errno)
67# define CREATE_THREAD(_S,_F,_P) ((Handle)_beginthreadex(0,_S,(UINT (WINAPI *)(void *))_F,(void *)_P,0,0))
68# define EXIT_THREAD _endthreadex(0)
69# define CLOSE_HANDLE(x) CloseHandle(x)
70# define THREAD_RETURN(x) return(x)
71# endif
72#else
73# define THREAD_CALL WINAPI
74# define THREAD_HANDLE HANDLE
75# define THREAD_RET_T DWORD
76# define CREATE_THREAD_FAILED (0L)
77# define CREATE_THREAD_ERROR GetLastError()
78# define CREATE_THREAD(_S,_F,_P) ((Handle)CreateThread(0,_S,(DWORD (WINAPI *)(void *))_F,(void *)_P,0,0))
79# define CREATE_THREAD2(_S,_F,_P,_ID) ((Handle)CreateThread(0,_S,(DWORD (WINAPI *)(void *))_F,(void *)_P,0,_ID))
80# define EXIT_THREAD ExitThread(0)
81# define CLOSE_HANDLE(x) CloseHandle(x)
82# define THREAD_RETURN(x) return(x)
83#endif
84
85#define InvalidHandle 0
86
87template
88<
89 typename Thread_T
90>
91class UTILITE_EXPORT UThreadC
92{
93 private:
94 struct Instance;
95
96 public:
97 typedef Thread_T & Thread_R;
98 typedef const Thread_T & Thread_C_R;
99
100 typedef THREAD_HANDLE Handle;
101 typedef void (* Handler)( Thread_R );
102
103 protected:
104 UThreadC() {}
105
106 virtual void ThreadMain( Thread_R ) = 0;
107
108 static void Exit()
109 { EXIT_THREAD; }
110
111 static void TestCancel()
112 { Sleep(0); }
113
114 static int Self()
115 {
116 Handle Hnd = InvalidHandle;
117 DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),GetCurrentProcess(),(LPHANDLE)&Hnd,NULL,0,NULL);
118 return Hnd;
119
120 // only a pseudo-handle!
121 //return (Handle)GetCurrentThread();
122 }
123
124 public:
125
126 static int Create(
127 const Handler & Function,
128 Thread_C_R Param,
129 Handle * const & H = 0,
130 const bool & CreateDetached = false,
131 const unsigned int & StackSize = 0,
132 const bool & CancelEnable = false, // UNUSED
133 const bool & CancelAsync = false // UNUSED
134 )
135 {
136 M_Create().lock();
137
138 Instance I(Param,0,Function);
139
140 Handle Hnd(CREATE_THREAD(StackSize,ThreadMainHandler,&I));
141
142 if ( Hnd == CREATE_THREAD_FAILED )
143 {
144 if ( H ) *H = InvalidHandle;
145 M_Create().unlock();
146 return CREATE_THREAD_ERROR;
147 }
148
149 if ( H ) *H = Hnd;
150
151 S_Create().Wait();
152 M_Create().unlock();
153
154 if ( CreateDetached ) CLOSE_HANDLE(Hnd);
155 return 0;
156 }
157
158 int Create(
159 Thread_C_R Param,
160 Handle * const & H = 0,
161 const bool & CreateDetached = false,
162 const unsigned int & StackSize = 0,
163 const bool & CancelEnable = false, // UNUSED
164 const bool & CancelAsync = false // UNUSED
165 ) const
166 {
167 M_Create().lock();
168
169 Instance I(Param,const_cast<UThreadC *>(this));
170
171 Handle Hnd(CREATE_THREAD(StackSize,ThreadMainHandler,&I));
172
173 if ( Hnd == CREATE_THREAD_FAILED )
174 {
175 if ( H ) *H = InvalidHandle;
176 M_Create().unlock();
177 return CREATE_THREAD_ERROR;
178 }
179
180 if ( H ) *H = Hnd;
181
182 S_Create().Wait();
183 M_Create().unlock();
184
185 if ( CreateDetached ) CLOSE_HANDLE(Hnd);
186 return 0;
187 }
188
189 static int Join( const Handle &H )
190 {
191 DWORD R = WaitForSingleObject((HANDLE)H,INFINITE);
192
193 if ( (R == WAIT_OBJECT_0) || (R == WAIT_ABANDONED) )
194 {
195 CLOSE_HANDLE(H);
196 return 0;
197 }
198
199 if ( R == WAIT_TIMEOUT ) return EAGAIN;
200 return EINVAL;
201 }
202
203 static int Kill( const Handle &H )
204 { return TerminateThread((HANDLE)H,0) ? 0 : EINVAL; }
205
206 static int Detach( const Handle &H )
207 { return (CLOSE_HANDLE(H)?0:EINVAL); }
208
209 private:
210
211 static const UMutex &M_Create() { static UMutex M; return M; }
212 static const USemaphore &S_Create() { static USemaphore S; return S; }
213
214 static THREAD_RET_T THREAD_CALL ThreadMainHandler( Instance *Param )
215 {
216 Instance I(*Param);
217 Thread_T Data(I.Data);
218 S_Create().Post();
219
220 if ( I.Owner )
221 I.Owner->ThreadMain(Data);
222 else
223 I.pFN(Data);
224
225 Exit();
226 THREAD_RETURN(0);
227 }
228
229 struct Instance
230 {
231 Instance( Thread_C_R P, UThreadC<Thread_T> *const &O, const typename UThreadC<Thread_T>::Handler &pH = 0 )
232 : pFN(pH), Data(P), Owner(O) {}
233
234 typename UThreadC<Thread_T>::Handler pFN;
235 typename UThreadC<Thread_T>::Thread_C_R Data;
236 UThreadC<Thread_T> * Owner;
237
238 };
239};
240
242// Explicit Specialization of void
243//
244template<>
245class UTILITE_EXPORT UThreadC<void>
246{
247 private:
248 struct Instance;
249
250 public:
251 typedef THREAD_HANDLE Handle;
252 typedef void ( *Handler)();
253
254 virtual ~UThreadC<void>() {}
255
256 protected:
257 UThreadC<void>() {}
258
259 virtual void ThreadMain() = 0;
260
261 static void Exit()
262 { EXIT_THREAD; }
263
264 static void TestCancel()
265 { Sleep(0); }
266
267 static int Self()
268 {
269 return (int)GetCurrentThreadId();
270 //Handle Hnd = InvalidHandle;
271 //DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),GetCurrentProcess(),(LPHANDLE)&Hnd,NULL,0,NULL);
272 //return Hnd;
273
274 // only a pseudo-handle!
275 //return (Handle)GetCurrentThread();
276 }
277
278 public:
279
280 static int Create(
281 const Handler & Function,
282 Handle * const & H = 0,
283 const bool & CreateDetached = false,
284 const unsigned int & StackSize = 0,
285 const bool & CancelEnable = false, // UNUSED
286 const bool & CancelAsync = false // UNUSED
287 )
288 {
289 Handle Hnd(CREATE_THREAD(StackSize,ThreadMainHandler_S,Function));
290
291 if ( Hnd == CREATE_THREAD_FAILED )
292 {
293 if ( H ) *H = InvalidHandle;
294 return (int)CREATE_THREAD_ERROR;
295 }
296
297 if ( H ) *H = Hnd;
298 if ( CreateDetached ) CLOSE_HANDLE(Hnd);
299 return 0;
300 }
301
302 int Create(
303 Handle * const & H = 0,
304 const bool & CreateDetached = false,
305 const unsigned int & StackSize = 0,
306 const bool & CancelEnable = false, // UNUSED
307 const bool & CancelAsync = false // UNUSED
308 ) const
309 {
310 Handle Hnd(CREATE_THREAD(StackSize,ThreadMainHandler,this));
311
312 if ( Hnd == CREATE_THREAD_FAILED )
313 {
314 if ( H ) *H = InvalidHandle;
315 return (int)CREATE_THREAD_ERROR;
316 }
317
318 if ( H ) *H = Hnd;
319 if ( CreateDetached ) CLOSE_HANDLE(Hnd);
320 Self();
321 return 0;
322 }
323
324 int Create(
325 unsigned long & ThreadId,
326 Handle * const & H = 0,
327 const bool & CreateDetached = false,
328 const unsigned int & StackSize = 0,
329 const bool & CancelEnable = false, // UNUSED
330 const bool & CancelAsync = false // UNUSED
331 ) const
332 {
333 *H = InvalidHandle;
334 int id;
335 *H = CREATE_THREAD2(StackSize,ThreadMainHandler,this, (LPDWORD)&id);
336 ThreadId = (unsigned long)id;
337
338 if ( *H == CREATE_THREAD_FAILED )
339 {
340 *H = InvalidHandle;
341 return (int)CREATE_THREAD_ERROR;
342 }
343
344 if ( CreateDetached ) CLOSE_HANDLE(*H);
345 return 0;
346 }
347
348 static int Join( const Handle &H )
349 {
350 DWORD R = WaitForSingleObject((HANDLE)H,INFINITE);
351
352 if ( (R == WAIT_OBJECT_0) || (R == WAIT_ABANDONED) )
353 {
354 CLOSE_HANDLE(H);
355 return 0;
356 }
357
358 if ( R == WAIT_TIMEOUT ) return EAGAIN;
359 return EINVAL;
360 }
361
362 static int Kill( const Handle &H )
363 { return TerminateThread((HANDLE)H,0) ? 0 : EINVAL; }
364
365 static int Detach( const Handle &H )
366 { return (CLOSE_HANDLE(H)?0:EINVAL); }
367
368 private:
369
370 static THREAD_RET_T THREAD_CALL ThreadMainHandler( UThreadC<void> *Param )
371 {
372 Param->ThreadMain();
373 Exit();
374 THREAD_RETURN(0);
375 }
376
377 static THREAD_RET_T THREAD_CALL ThreadMainHandler_S( Handler Param )
378 {
379 Param();
380 Exit();
381 THREAD_RETURN(0);
382 }
383};
384
385#endif // !_U_Thread_Win32_