Win32/UThreadC.h
Go to the documentation of this file.
1 // 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 
41 #include "rtabmap/utilite/UMutex.h"
42 
43 inline void uSleep(unsigned int ms)
44 {
45  Sleep(ms);
46 }
47 
48 #ifdef _CRT_
49 # include <process.h>
50 # ifdef _USE_BEGINTHREAD
51 # define THREAD_CALL __cdecl
52 # define THREAD_HANDLE uintptr_t
53 # define THREAD_RET_T void
54 # define CREATE_THREAD_FAILED (-1L)
55 # define CREATE_THREAD_ERROR (errno)
56 # define CREATE_THREAD(_S,_F,_P) ((Handle)_beginthread((void (__cdecl *)(void *))_F,_S,(void *)_P))
57 # define EXIT_THREAD _endthread()
58 # define CLOSE_HANDLE(x) 1
59 # define THREAD_RETURN(x) return
60 # else
61 # define THREAD_CALL WINAPI
62 # define THREAD_HANDLE HANDLE
63 # define THREAD_RET_T UINT
64 # define CREATE_THREAD_FAILED (0L)
65 # define CREATE_THREAD_ERROR (errno)
66 # define CREATE_THREAD(_S,_F,_P) ((Handle)_beginthreadex(0,_S,(UINT (WINAPI *)(void *))_F,(void *)_P,0,0))
67 # define EXIT_THREAD _endthreadex(0)
68 # define CLOSE_HANDLE(x) CloseHandle(x)
69 # define THREAD_RETURN(x) return(x)
70 # endif
71 #else
72 # define THREAD_CALL WINAPI
73 # define THREAD_HANDLE HANDLE
74 # define THREAD_RET_T DWORD
75 # define CREATE_THREAD_FAILED (0L)
76 # define CREATE_THREAD_ERROR GetLastError()
77 # define CREATE_THREAD(_S,_F,_P) ((Handle)CreateThread(0,_S,(DWORD (WINAPI *)(void *))_F,(void *)_P,0,0))
78 # define CREATE_THREAD2(_S,_F,_P,_ID) ((Handle)CreateThread(0,_S,(DWORD (WINAPI *)(void *))_F,(void *)_P,0,_ID))
79 # define EXIT_THREAD ExitThread(0)
80 # define CLOSE_HANDLE(x) CloseHandle(x)
81 # define THREAD_RETURN(x) return(x)
82 #endif
83 
84 #define InvalidHandle 0
85 
86 template
87 <
88  typename Thread_T
89 >
91 {
92  private:
93  struct Instance;
94 
95  public:
96  typedef Thread_T & Thread_R;
97  typedef const Thread_T & Thread_C_R;
98 
100  typedef void (* Handler)( Thread_R );
101 
102  protected:
103  UThreadC() {}
104 
105  virtual void ThreadMain( Thread_R ) = 0;
106 
107  static void Exit()
108  { EXIT_THREAD; }
109 
110  static void TestCancel()
111  { Sleep(0); }
112 
113  static int Self()
114  {
115  Handle Hnd = InvalidHandle;
116  DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),GetCurrentProcess(),(LPHANDLE)&Hnd,NULL,0,NULL);
117  return Hnd;
118 
119  // only a pseudo-handle!
120  //return (Handle)GetCurrentThread();
121  }
122 
123  public:
124 
125  static int Create(
126  const Handler & Function,
127  Thread_C_R Param,
128  Handle * const & H = 0,
129  const bool & CreateDetached = false,
130  const unsigned int & StackSize = 0,
131  const bool & CancelEnable = false, // UNUSED
132  const bool & CancelAsync = false // UNUSED
133  )
134  {
135  M_Create().lock();
136 
137  Instance I(Param,0,Function);
138 
139  Handle Hnd(CREATE_THREAD(StackSize,ThreadMainHandler,&I));
140 
141  if ( Hnd == CREATE_THREAD_FAILED )
142  {
143  if ( H ) *H = InvalidHandle;
144  M_Create().unlock();
145  return CREATE_THREAD_ERROR;
146  }
147 
148  if ( H ) *H = Hnd;
149 
150  S_Create().Wait();
151  M_Create().unlock();
152 
153  if ( CreateDetached ) CLOSE_HANDLE(Hnd);
154  return 0;
155  }
156 
157  int Create(
158  Thread_C_R Param,
159  Handle * const & H = 0,
160  const bool & CreateDetached = false,
161  const unsigned int & StackSize = 0,
162  const bool & CancelEnable = false, // UNUSED
163  const bool & CancelAsync = false // UNUSED
164  ) const
165  {
166  M_Create().lock();
167 
168  Instance I(Param,const_cast<UThreadC *>(this));
169 
170  Handle Hnd(CREATE_THREAD(StackSize,ThreadMainHandler,&I));
171 
172  if ( Hnd == CREATE_THREAD_FAILED )
173  {
174  if ( H ) *H = InvalidHandle;
175  M_Create().unlock();
176  return CREATE_THREAD_ERROR;
177  }
178 
179  if ( H ) *H = Hnd;
180 
181  S_Create().Wait();
182  M_Create().unlock();
183 
184  if ( CreateDetached ) CLOSE_HANDLE(Hnd);
185  return 0;
186  }
187 
188  static int Join( const Handle &H )
189  {
190  DWORD R = WaitForSingleObject((HANDLE)H,INFINITE);
191 
192  if ( (R == WAIT_OBJECT_0) || (R == WAIT_ABANDONED) )
193  {
194  CLOSE_HANDLE(H);
195  return 0;
196  }
197 
198  if ( R == WAIT_TIMEOUT ) return EAGAIN;
199  return EINVAL;
200  }
201 
202  static int Kill( const Handle &H )
203  { return TerminateThread((HANDLE)H,0) ? 0 : EINVAL; }
204 
205  static int Detach( const Handle &H )
206  { return (CLOSE_HANDLE(H)?0:EINVAL); }
207 
208  private:
209 
210  static const UMutex &M_Create() { static UMutex M; return M; }
211  static const USemaphore &S_Create() { static USemaphore S; return S; }
212 
214  {
215  Instance I(*Param);
216  Thread_T Data(I.Data);
217  S_Create().Post();
218 
219  if ( I.Owner )
220  I.Owner->ThreadMain(Data);
221  else
222  I.pFN(Data);
223 
224  Exit();
225  THREAD_RETURN(0);
226  }
227 
228  struct Instance
229  {
230  Instance( Thread_C_R P, UThreadC<Thread_T> *const &O, const typename UThreadC<Thread_T>::Handler &pH = 0 )
231  : pFN(pH), Data(P), Owner(O) {}
232 
235  UThreadC<Thread_T> * Owner;
236 
237  };
238 };
239 
241 // Explicit Specialization of void
242 //
243 template<>
244 class UTILITE_EXP UThreadC<void>
245 {
246  private:
247  struct Instance;
248 
249  public:
250  typedef THREAD_HANDLE Handle;
251  typedef void ( *Handler)();
252 
253  virtual ~UThreadC<void>() {}
254 
255  protected:
257 
258  virtual void ThreadMain() = 0;
259 
260  static void Exit()
261  { EXIT_THREAD; }
262 
263  static void TestCancel()
264  { Sleep(0); }
265 
266  static int Self()
267  {
268  return (int)GetCurrentThreadId();
269  //Handle Hnd = InvalidHandle;
270  //DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),GetCurrentProcess(),(LPHANDLE)&Hnd,NULL,0,NULL);
271  //return Hnd;
272 
273  // only a pseudo-handle!
274  //return (Handle)GetCurrentThread();
275  }
276 
277  public:
278 
279  static int Create(
280  const Handler & Function,
281  Handle * const & H = 0,
282  const bool & CreateDetached = false,
283  const unsigned int & StackSize = 0,
284  const bool & CancelEnable = false, // UNUSED
285  const bool & CancelAsync = false // UNUSED
286  )
287  {
288  Handle Hnd(CREATE_THREAD(StackSize,ThreadMainHandler_S,Function));
289 
290  if ( Hnd == CREATE_THREAD_FAILED )
291  {
292  if ( H ) *H = InvalidHandle;
293  return (int)CREATE_THREAD_ERROR;
294  }
295 
296  if ( H ) *H = Hnd;
297  if ( CreateDetached ) CLOSE_HANDLE(Hnd);
298  return 0;
299  }
300 
301  int Create(
302  Handle * const & H = 0,
303  const bool & CreateDetached = false,
304  const unsigned int & StackSize = 0,
305  const bool & CancelEnable = false, // UNUSED
306  const bool & CancelAsync = false // UNUSED
307  ) const
308  {
309  Handle Hnd(CREATE_THREAD(StackSize,ThreadMainHandler,this));
310 
311  if ( Hnd == CREATE_THREAD_FAILED )
312  {
313  if ( H ) *H = InvalidHandle;
314  return (int)CREATE_THREAD_ERROR;
315  }
316 
317  if ( H ) *H = Hnd;
318  if ( CreateDetached ) CLOSE_HANDLE(Hnd);
319  Self();
320  return 0;
321  }
322 
323  int Create(
324  unsigned long & ThreadId,
325  Handle * const & H = 0,
326  const bool & CreateDetached = false,
327  const unsigned int & StackSize = 0,
328  const bool & CancelEnable = false, // UNUSED
329  const bool & CancelAsync = false // UNUSED
330  ) const
331  {
332  *H = InvalidHandle;
333  int id;
334  *H = CREATE_THREAD2(StackSize,ThreadMainHandler,this, (LPDWORD)&id);
335  ThreadId = (unsigned long)id;
336 
337  if ( *H == CREATE_THREAD_FAILED )
338  {
339  *H = InvalidHandle;
340  return (int)CREATE_THREAD_ERROR;
341  }
342 
343  if ( CreateDetached ) CLOSE_HANDLE(*H);
344  return 0;
345  }
346 
347  static int Join( const Handle &H )
348  {
349  DWORD R = WaitForSingleObject((HANDLE)H,INFINITE);
350 
351  if ( (R == WAIT_OBJECT_0) || (R == WAIT_ABANDONED) )
352  {
353  CLOSE_HANDLE(H);
354  return 0;
355  }
356 
357  if ( R == WAIT_TIMEOUT ) return EAGAIN;
358  return EINVAL;
359  }
360 
361  static int Kill( const Handle &H )
362  { return TerminateThread((HANDLE)H,0) ? 0 : EINVAL; }
363 
364  static int Detach( const Handle &H )
365  { return (CLOSE_HANDLE(H)?0:EINVAL); }
366 
367  private:
368 
370  {
371  Param->ThreadMain();
372  Exit();
373  THREAD_RETURN(0);
374  }
375 
377  {
378  Param();
379  Exit();
380  THREAD_RETURN(0);
381  }
382 };
383 
384 #endif // !_U_Thread_Win32_
Thread_T & Thread_R
#define NULL
#define CREATE_THREAD_ERROR
int Create(unsigned long &ThreadId, Handle *const &H=0, const bool &CreateDetached=false, const unsigned int &StackSize=0, const bool &CancelEnable=false, const bool &CancelAsync=false) const
static THREAD_RET_T THREAD_CALL ThreadMainHandler(Instance *Param)
static int Self()
static int Create(const Handler &Function, Handle *const &H=0, const bool &CreateDetached=false, const unsigned int &StackSize=0, const bool &CancelEnable=false, const bool &CancelAsync=false)
#define CLOSE_HANDLE(x)
#define UTILITE_EXP
Definition: UtiLiteExp.h:33
#define THREAD_CALL
static int Create(const Handler &Function, Thread_C_R Param, Handle *const &H=0, const bool &CreateDetached=false, const unsigned int &StackSize=0, const bool &CancelEnable=false, const bool &CancelAsync=false)
#define CREATE_THREAD(_S, _F, _P)
UThreadC< Thread_T >::Thread_C_R Data
static THREAD_RET_T THREAD_CALL ThreadMainHandler(UThreadC< void > *Param)
Instance(Thread_C_R P, UThreadC< Thread_T > *const &O, const typename UThreadC< Thread_T >::Handler &pH=0)
THREAD_HANDLE Handle
#define THREAD_RETURN(x)
static int Join(const Handle &H)
#define THREAD_HANDLE
static int Kill(const Handle &H)
const Thread_T & Thread_C_R
void uSleep(unsigned int ms)
Definition: UMutex.h:54
static int Detach(const Handle &H)
static THREAD_RET_T THREAD_CALL ThreadMainHandler_S(Handler Param)
static void TestCancel()
virtual void ThreadMain()=0
UThreadC< Thread_T > * Owner
UThreadC< Thread_T >::Handler pFN
#define THREAD_RET_T
static int Join(const Handle &H)
static const UMutex & M_Create()
#define InvalidHandle
#define CREATE_THREAD_FAILED
#define CREATE_THREAD2(_S, _F, _P, _ID)
static int Detach(const Handle &H)
#define EXIT_THREAD
static int Self()
static void TestCancel()
static const USemaphore & S_Create()
static void Exit()
int Create(Handle *const &H=0, const bool &CreateDetached=false, const unsigned int &StackSize=0, const bool &CancelEnable=false, const bool &CancelAsync=false) const
THREAD_HANDLE Handle
static void Exit()
int Create(Thread_C_R Param, Handle *const &H=0, const bool &CreateDetached=false, const unsigned int &StackSize=0, const bool &CancelEnable=false, const bool &CancelAsync=false) const
static int Kill(const Handle &H)


rtabmap
Author(s): Mathieu Labbe
autogenerated on Mon Jan 23 2023 03:38:58