Gray C++ Libraries  0.0.2
A set of C++ libraries for MSVC, GNU on Windows, WinCE, Linux
cThread.h
Go to the documentation of this file.
1 //
5 //
6 
7 #ifndef _INC_cThread_H
8 #define _INC_cThread_H
9 #ifndef NO_PRAGMA_ONCE
10 #pragma once
11 #endif
12 
13 #include "../GrayLibBase.h"
21 
22 #ifdef _MFC_VER
23 #include <atlutil.h>
24 #endif
25 
26 namespace GrayLib
27 {
29 
30 #ifdef _WIN32
31  typedef HANDLE THREADHANDLE_t; // cOSHandle in WIN32 but not in __linux__
32  static const THREADHANDLE_t THREADHANDLE_NULL = HANDLE_NULL;
33 #elif defined(__linux__)
34  typedef THREADID_t THREADHANDLE_t; // same as THREADID_t pthread_t
35  static const THREADHANDLE_t THREADHANDLE_NULL = cThreadId::k_NULL;
36 #else
37 #error NOOS
38 #endif
39 
40 #ifdef _MFC_VER
41  typedef CWorkerThread<> cThreadBase; // GetThreadId
42 #else
43  class GRAYLIB_LINK cThreadBase : public CObject, public cThreadId // GetThreadId
44  {
49 
50  protected:
51  THREADHANDLE_t m_hThread;
52 
53  public:
54  cThreadBase() noexcept
55  : m_hThread(THREADHANDLE_NULL)
56  {
57  }
58  virtual ~cThreadBase()
59  {
60  }
61  };
62 #endif // _MFC_VER
63 
64  class cThread;
66 
67  class GRAYLIB_LINK cThread : public cThreadBase, public cRefBase, public cThreadState
68  {
73 
74  friend class cThreadMgr;
75 
76  protected:
79 
80 #ifdef __linux__
81  THREAD_EXITCODE_t m_nExitCode;
82 #endif
83 
84  protected:
85  virtual bool ThreadTick()
86  {
91 
92  ASSERT(isCurrentThread()); // only call from self thread.
93  return !isThreadStopping();
94  }
95 
97  virtual THREAD_EXITCODE_t Run();
98 
99  THREAD_EXITCODE_t RunDirectly();
100 
102  static THREAD_EXITCODE_t _stdcall EntryProc(void* pThisThread);
103 
105  virtual void onThreadCreate();
106  virtual void onThreadExit(THREAD_EXITCODE_t nExitCode);
107  void onThreadTerminated(THREAD_EXITCODE_t nExitCode);
108 
109  public:
110  cThread();
111  virtual ~cThread();
112 
113  static cThread* GRAYCALL GetCurrentThread();
114  static bool GRAYCALL IsCurrentThreadStopping();
115 
116  bool isValidThreadHandle() const noexcept
117  {
120  return this->m_hThread != THREADHANDLE_NULL;
121  }
122 
123  THREADID_t get_HashCode() const noexcept
124  {
126  return this->m_dwThreadId;
127  }
128 #ifdef _MFC_VER
129  bool isCurrentThread() const
130  {
132  return cThreadId::IsEqualId(this->get_HashCode(), cThreadId::GetCurrentId());
133  }
134 #endif
135 
136  virtual bool isValidCheck() const noexcept;
137 
138 #if defined(_WIN32) && defined(_MSC_VER) && ! defined(UNDER_CE)
139  static void GRAYCALL SetThreadName(THREADID_t dwThreadID, const char* pszThreadName);
140  bool put_ThreadName(const char* pszThreadName);
141 #endif
142  STDMETHOD_(cString, get_Name)() const;
143 
144  bool isThreadSleeping() const noexcept
145  {
146  return m_bThreadSleeping;
147  }
148  THREAD_EXITCODE_t get_ExitCodeThread() const;
149 
150  int get_ThreadPriority() const;
151  bool put_ThreadPriority(int nPriority);
152 
153  bool SuspendThread();
154  bool ResumeThread();
155 
156  virtual HRESULT SleepThread(TIMESYSD_t dwWaitMillisec = 1, bool bAlertable = false);
157  virtual void WakeThread();
158 
159  virtual bool RequestStopThread(bool bWillWait = false) noexcept override;
160  bool ExitCurrentThread(THREAD_EXITCODE_t nExitCode = THREAD_EXITCODE_OK);
161 
162  bool WaitForThreadExit(TIMESYSD_t nMilliSec = cTimeSys::k_FREQ);
163  THREAD_EXITCODE_t WaitForThreadExitCode(TIMESYSD_t iTimeMSec = cTimeSys::k_FREQ);
164 
165  bool TerminateThread(THREAD_EXITCODE_t iExitCode = THREAD_EXITCODE_ERR, TIMESYSD_t nMilliSec = 0);
166 
167  static void GRAYCALL RequestStopThreadArray(bool bWillWait, cThread** ppThreads, size_t nThreads);
168  static void GRAYCALL TerminateThreadArray(THREAD_EXITCODE_t nExitCode, TIMESYSD_t iTimeMSec, cThread** ppThreads, size_t nThreads);
169 
170  void AttachToCurrentThread();
171 
172  HRESULT CreateThread(THREAD_FUNC_t pEntryProc, void* pArgs, DWORD dwCreationFlags = 0);
173 
174  virtual HRESULT CreateThread(DWORD dwCreationFlags = 0)
175  {
178  return CreateThread(EntryProc, this, dwCreationFlags);
179  }
180 
181  void CloseThread();
182 
183 #ifdef _WIN32
184  bool GetStatTimes(FILETIME* pKernelTime, FILETIME* pUserTime) const
185  {
188  return ::GetThreadTimes(m_hThread, nullptr, nullptr, pKernelTime, pUserTime) ? true : false;
189  }
190 #endif
191 
192 #if defined(_MT)
193  UNITTEST_FRIEND(cThread);
194 #endif
195  };
196 
198  {
202  typedef cThread SUPER_t;
203 
204  public:
210 
211  protected:
213 
214  private:
216  UINT m_nCriticalWaitCount;
217 
218  protected:
219  virtual bool ThreadTick() override
220  {
224  m_nThreadTicks++;
225  return SUPER_t::ThreadTick();
226  }
227  virtual void onThreadCreate() override;
228 
229  public:
230  cThreadChecked();
231  virtual ~cThreadChecked();
232 
233  virtual bool CheckStuckThread(TIMESYSD_t iMilliSecTilStuck, bool bTerminateAndRestart);
234 
235  UINT get_ThreadTicks() const
236  {
237  return m_nThreadTicks;
238  }
239  bool isCriticalWait() const
240  {
242  return m_nCriticalWaitCount ? true : false;
243  }
244  void ChangeCriticalWait(int iDelta)
245  {
247  ASSERT(isCurrentThread());
248  m_nCriticalWaitCount += iDelta;
249  }
250 
251  static cThreadChecked* GRAYCALL GetCurrentThreadChecked();
252  };
253 
254  template <class _TYPE>
256  {
260 
261  typedef cThreadChecked SUPER_t;
262 
263  protected:
264  static THREAD_EXITCODE_t _stdcall EntryProc(void* pThisThread)
265  {
267  return SUPER_t::EntryProc(pThisThread);
268  }
269  public:
270  virtual HRESULT CreateThread(DWORD dwCreationFlags = 0) override // start/restart this thread! default RunDirectly() then Run() body
271  {
273  return SUPER_t::CreateThread(EntryProc, this, dwCreationFlags);
274  }
275  };
276 }
277 #endif // _INC_cThread_H
#define GRAYCALL
declare calling convention for static functions so everyone knows the arg passing scheme....
Definition: GrayCore.h:36
#define GRAYLIB_LINK
Definition: GrayLibBase.h:35
INT32 HRESULT
_WIN32 style error codes. INT32
Definition: SysTypes.h:465
#define ASSERT(exp)
Definition: cDebugAssert.h:87
#define HANDLE_NULL
Invalid OS handle for _WIN32. Not invalid OS handle for linux.
Definition: cOSHandle.h:21
#define UNITTEST_FRIEND(n)
Define this in the class body to be unit tested. Allow the unit test to access private/protected stuf...
Definition: cUnitTestDecl.h:17
Definition: cThread.h:44
virtual ~cThreadBase()
Definition: cThread.h:58
cThreadBase() noexcept
Definition: cThread.h:54
THREADHANDLE_t m_hThread
there may be many handles to the same THREADID_t in _WIN32. I must call CloseThread() on this.
Definition: cThread.h:51
Definition: cThread.h:198
cTimeSys m_tStart
When did thread first run ?
Definition: cThread.h:207
UINT m_nThreadTicksLast
checked periodically by outside observer.
Definition: cThread.h:206
UINT m_nThreadTicks
periodically increment this to make sure the thread is alive!
Definition: cThread.h:212
UINT m_nRecoveryStage
What have we done about being stuck ?
Definition: cThread.h:209
virtual bool ThreadTick() override
Definition: cThread.h:219
UINT get_ThreadTicks() const
Definition: cThread.h:235
void ChangeCriticalWait(int iDelta)
Definition: cThread.h:244
bool isCriticalWait() const
Definition: cThread.h:239
TIMESYS_t m_timeLastChanged
Last outside detected tick change time.
Definition: cThread.h:208
Definition: cThreadMgr.h:26
Definition: cThread.h:256
static THREAD_EXITCODE_t _stdcall EntryProc(void *pThisThread)
Definition: cThread.h:264
virtual HRESULT CreateThread(DWORD dwCreationFlags=0) override
Definition: cThread.h:270
Definition: cThread.h:68
bool isValidThreadHandle() const noexcept
Definition: cThread.h:116
STDMETHOD_(cString, get_Name)() const
override memory allocation and structure definitions are valid.
static THREAD_EXITCODE_t _stdcall EntryProc(void *pThisThread)
_WorkerThreadProc
Definition: cThread.cpp:693
bool m_bThreadSleeping
Idle worker threads waiting for something to do. inside Sleep() or WaitForSingleObject()
Definition: cThread.h:77
virtual bool ThreadTick()
Definition: cThread.h:85
HRESULT CreateThread(THREAD_FUNC_t pEntryProc, void *pArgs, DWORD dwCreationFlags=0)
Definition: cThread.cpp:167
THREADID_t get_HashCode() const noexcept
Definition: cThread.h:123
bool m_bThreadSuspended
May be resumed. inside Suspend() -> Resume()
Definition: cThread.h:78
bool isThreadSleeping() const noexcept
Definition: cThread.h:144
Definition: cObject.h:67
Definition: cRefPtr.h:22
Definition: cRefPtr.h:225
Definition: cThreadLock.h:55
static THREADID_t GetCurrentId() noexcept
Definition: cThreadLock.h:97
static bool IsEqualId(THREADID_t a, THREADID_t b) noexcept
Definition: cThreadLock.h:113
static const THREADID_t k_NULL
Not a valid thread Id.
Definition: cThreadLock.h:64
Definition: cThreadLock.h:137
Definition: cTimeSys.h:93
Definition: cMesh.h:22
cRefPtr< cThread > cThreadPtr
Definition: cThread.h:64
UNITTEST2_PREDEF(cQuadtree)
INT32 TIMESYSD_t
Time delta. signed milli-Seconds Span. cTimeSys::k_DMAX, cTimeSys::k_INF = MAILSLOT_WAIT_FOREVER.
Definition: cTimeSys.h:28
THREAD_EXITCODE_t(_stdcall * THREAD_FUNC_t)(void *)
Definition: cThreadLock.h:52
UINT32 TIMESYS_t
TIMESYS_t = The normal system tick timer. milli-seconds since start of system/app ?
Definition: cTimeSys.h:27