开源的socket服务端客户端,支持C# C++

Thread.h 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. * Copyright: JessMA Open Source (ldcsaa@gmail.com)
  3. *
  4. * Version : 2.3.17
  5. * Author : Bruce Liang
  6. * Website : http://www.jessma.org
  7. * Project : https://github.com/ldcsaa
  8. * Blog : http://www.cnblogs.com/ldcsaa
  9. * Wiki : http://www.oschina.net/p/hp-socket
  10. * QQ Group : 75375912
  11. *
  12. * Licensed under the Apache License, Version 2.0 (the "License");
  13. * you may not use this file except in compliance with the License.
  14. * You may obtain a copy of the License at
  15. *
  16. * http://www.apache.org/licenses/LICENSE-2.0
  17. *
  18. * Unless required by applicable law or agreed to in writing, software
  19. * distributed under the License is distributed on an "AS IS" BASIS,
  20. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  21. * See the License for the specific language governing permissions and
  22. * limitations under the License.
  23. */
  24. #pragma once
  25. #include <process.h>
  26. #include "RWLock.h"
  27. #include "STLHelper.h"
  28. template<class T> class CThread
  29. {
  30. private:
  31. typedef UINT (T::*F)();
  32. public:
  33. BOOL Start(T* pRunner, F pFunc, int iPriority = THREAD_PRIORITY_NORMAL, UINT uiStackSize = 0, LPSECURITY_ATTRIBUTES lpThreadAttributes = nullptr)
  34. {
  35. BOOL isOK = TRUE;
  36. if(!IsRunning())
  37. {
  38. Release();
  39. m_pRunner = pRunner;
  40. m_pFunc = pFunc;
  41. if(iPriority == THREAD_PRIORITY_NORMAL)
  42. m_hThread = (HANDLE)_beginthreadex(lpThreadAttributes, uiStackSize, ThreadProc, (LPVOID)this, 0, &m_uiThreadID);
  43. else
  44. {
  45. m_hThread = (HANDLE)_beginthreadex(lpThreadAttributes, uiStackSize, ThreadProc, (LPVOID)this, CREATE_SUSPENDED, &m_uiThreadID);
  46. if(IsValid())
  47. {
  48. ::SetThreadPriority(m_hThread, iPriority);
  49. ::ResumeThread(m_hThread);
  50. }
  51. }
  52. if(!IsValid())
  53. {
  54. ::SetLastError(_doserrno);
  55. isOK = FALSE;
  56. }
  57. }
  58. else
  59. {
  60. ::SetLastError(ERROR_INVALID_STATE);
  61. isOK = FALSE;
  62. }
  63. return isOK;
  64. }
  65. BOOL Join(BOOL bWithMessageLoop = FALSE, DWORD dwMilliseconds = INFINITE)
  66. {
  67. BOOL isOK = bWithMessageLoop ?
  68. ::MsgWaitForSingleObject(m_hThread, dwMilliseconds) :
  69. ::WaitForSingleObject(m_hThread, dwMilliseconds) == WAIT_OBJECT_0 ;
  70. Release();
  71. return isOK;
  72. }
  73. BOOL IsRunning()
  74. {
  75. if(!IsValid())
  76. return FALSE;
  77. DWORD dwExitCode;
  78. if(GetExitCode(&dwExitCode))
  79. return dwExitCode == STILL_ACTIVE;
  80. return FALSE;
  81. }
  82. VOID Release()
  83. {
  84. if(IsValid())
  85. {
  86. ::CloseHandle(m_hThread);
  87. Reset();
  88. }
  89. }
  90. HANDLE Detatch()
  91. {
  92. HANDLE h = m_hThread;
  93. Reset();
  94. return h;
  95. }
  96. BOOL Terminate (DWORD dwExitCode) {return ::TerminateThread(m_hThread, dwExitCode);}
  97. BOOL GetExitCode (LPDWORD lpExitCode) {return ::GetExitCodeThread(m_hThread, lpExitCode);}
  98. DWORD Suspend () {return ::SuspendThread(m_hThread);}
  99. DWORD Resume () {return ::ResumeThread(m_hThread);}
  100. BOOL IsValid () {return m_hThread != nullptr;}
  101. T* GetRunner () {return m_pRunner;}
  102. F GetFunc () {return m_pFunc;}
  103. DWORD GetThreadID () {return m_uiThreadID;}
  104. HANDLE& GetThreadHandle () {return m_hThread;}
  105. const HANDLE& GetThreadHandle () const {return m_hThread;}
  106. public:
  107. CThread()
  108. {
  109. Reset();
  110. }
  111. virtual ~CThread()
  112. {
  113. Release();
  114. }
  115. private:
  116. static UINT WINAPI ThreadProc(LPVOID pv)
  117. {
  118. CThread* pThis = (CThread*)pv;
  119. return ((pThis->m_pRunner)->*(pThis->m_pFunc))();
  120. }
  121. void Reset()
  122. {
  123. m_uiThreadID = 0;
  124. m_hThread = nullptr;
  125. m_pRunner = nullptr;
  126. m_pFunc = nullptr;
  127. }
  128. private:
  129. UINT m_uiThreadID;
  130. HANDLE m_hThread;
  131. T* m_pRunner;
  132. F m_pFunc;
  133. DECLARE_NO_COPY_CLASS(CThread)
  134. };
  135. template<class T, typename construct_param_type = void*> class CTlsObj
  136. {
  137. typedef unordered_map<DWORD, T*> TLocalMap;
  138. typedef typename TLocalMap::iterator TLocalMapI;
  139. typedef typename TLocalMap::const_iterator TLocalMapCI;
  140. public:
  141. T* TryGet(DWORD dwTID = 0)
  142. {
  143. T* pValue = nullptr;
  144. if(dwTID == 0) dwTID = ::GetCurrentThreadId();
  145. {
  146. CReadLock locallock(m_lock);
  147. TLocalMapCI it = m_map.find(dwTID);
  148. if(it != m_map.end())
  149. pValue = it->second;
  150. }
  151. return pValue;
  152. }
  153. T* Get()
  154. {
  155. DWORD dwTID = ::GetCurrentThreadId();
  156. T* pValue = TryGet(dwTID);
  157. if(pValue == nullptr)
  158. {
  159. CWriteLock locallock(m_lock);
  160. TLocalMapCI it = m_map.find(dwTID);
  161. if(it != m_map.end())
  162. pValue = it->second;
  163. if(pValue == nullptr)
  164. {
  165. pValue = Construct();
  166. m_map[dwTID] = pValue;
  167. }
  168. }
  169. return pValue;
  170. }
  171. T& GetRef()
  172. {
  173. return *Get();
  174. }
  175. T* Get(construct_param_type construct_param)
  176. {
  177. DWORD dwTID = ::GetCurrentThreadId();
  178. T* pValue = TryGet(dwTID);
  179. if(pValue == nullptr)
  180. {
  181. CWriteLock locallock(m_lock);
  182. TLocalMapCI it = m_map.find(dwTID);
  183. if(it != m_map.end())
  184. pValue = it->second;
  185. if(pValue == nullptr)
  186. {
  187. pValue = ConstructWithParam(construct_param);
  188. m_map[dwTID] = pValue;
  189. }
  190. }
  191. return pValue;
  192. }
  193. T& GetRef(construct_param_type construct_param)
  194. {
  195. return *Get(construct_param);
  196. }
  197. T* SetAndRetriveOldValue(T* pValue)
  198. {
  199. DWORD dwTID = ::GetCurrentThreadId();
  200. T* pOldValue = TryGet(dwTID);
  201. if(pValue != pOldValue)
  202. {
  203. CWriteLock locallock(m_lock);
  204. m_map[dwTID] = pValue;
  205. }
  206. return pOldValue;
  207. }
  208. void Set(T* pValue)
  209. {
  210. T* pOldValue = SetAndRetriveOldValue(pValue);
  211. if(pValue != pOldValue)
  212. Delete(pOldValue);
  213. }
  214. void Remove()
  215. {
  216. DWORD dwTID = ::GetCurrentThreadId();
  217. T* pOldValue = TryGet(dwTID);
  218. Delete(pOldValue);
  219. {
  220. CWriteLock locallock(m_lock);
  221. m_map.erase(dwTID);
  222. }
  223. }
  224. void Clear()
  225. {
  226. CWriteLock locallock(m_lock);
  227. if(!IsEmpty())
  228. {
  229. for(TLocalMapCI it = m_map.begin(); it != m_map.end(); ++it)
  230. Delete(it->second);
  231. m_map.clear();
  232. }
  233. }
  234. TLocalMap& GetLocalMap() {return m_map;}
  235. const TLocalMap& GetLocalMap() const {return m_map;}
  236. T* operator -> () {return Get();}
  237. const T* operator -> () const {return Get();}
  238. T& operator * () {return GetRef();}
  239. const T& operator * () const {return GetRef();}
  240. size_t Size () const {return m_map.size();}
  241. bool IsEmpty () const {return m_map.empty();}
  242. public:
  243. CTlsObj()
  244. {
  245. }
  246. ~CTlsObj()
  247. {
  248. Clear();
  249. }
  250. private:
  251. static inline void Delete(T* pValue)
  252. {
  253. if(pValue != nullptr)
  254. delete pValue;
  255. }
  256. static inline T* Construct()
  257. {
  258. return new T;
  259. }
  260. static inline T* ConstructWithParam(construct_param_type construct_param)
  261. {
  262. return new T(construct_param);
  263. }
  264. private:
  265. CSimpleRWLock m_lock;
  266. TLocalMap m_map;
  267. DECLARE_NO_COPY_CLASS(CTlsObj)
  268. };