Win32Thread.cpp
上传用户:chinafayin
上传日期:2022-04-05
资源大小:153k
文件大小:12k
源码类别:

并行计算

开发平台:

Visual C++

  1. //
  2. // OpenThread library, Copyright (C) 2002 - 2003  The Open Thread Group
  3. //
  4. // This library is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU Lesser General Public
  6. // License as published by the Free Software Foundation; either
  7. // version 2.1 of the License, or (at your option) any later version.
  8. //
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. // Lesser General Public License for more details.
  13. // 
  14. // You should have received a copy of the GNU Lesser General Public
  15. // License along with this library; if not, write to the Free Software
  16. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17. // 
  18. //
  19. // Win32Thread.c++ - C++ Thread class built on top of posix threads.
  20. // ~~~~~~~~~~~
  21. #include <memory>
  22. #include <string>
  23. using std::size_t;
  24. #include "Win32ThreadPrivateData.h"
  25. using namespace OpenThreads;
  26. Win32ThreadPrivateData::TlsHolder Win32ThreadPrivateData::TLS;
  27. Win32ThreadPrivateData::~Win32ThreadPrivateData()
  28. {
  29. }
  30. const std::string OPENTHREAD_VERSION_STRING = "OpenThread v1.2preAlpha, WindowThreads (Public Implementation)";
  31. //-----------------------------------------------------------------------------
  32. // Initialize thread master priority level
  33. //
  34. Thread::ThreadPriority Thread::s_masterThreadPriority =  Thread::PRIORITY_DEFAULT;
  35. bool Thread::s_isInitialized = false;
  36. //-----------------------------------------------------------------------------
  37. // Class to support some static methods necessary for pthread's to work
  38. // correctly.
  39. //
  40. namespace OpenThreads {
  41. class ThreadPrivateActions {
  42. //-------------------------------------------------------------------------
  43. // We're friendly to Thread, so it can issue the methods.
  44. //
  45. friend class Thread;
  46. private:
  47. //-------------------------------------------------------------------------
  48. // Win32Threads standard start routine.
  49. //
  50. static unsigned long __stdcall StartThread(void *data) {
  51. Thread *thread = static_cast<Thread *>(data);
  52. Win32ThreadPrivateData *pd =
  53. static_cast<Win32ThreadPrivateData *>(thread->_prvData);
  54. TlsSetValue(Win32ThreadPrivateData::TLS.ID ,data);
  55. //---------------------------------------------------------------------
  56. // Set the proper scheduling priorities
  57. //
  58. SetThreadSchedulingParams(thread);
  59. pd->isRunning = true;
  60. pd->isCanceled = false;
  61. try{
  62. thread->run();
  63. }
  64. catch(...)
  65. {
  66. // abnormal termination but must be caught in win32 anyway
  67. }
  68. pd->isRunning = false;
  69. return 0;
  70. };
  71. //-------------------------------------------------------------------------
  72. // Print information related to thread schduling parameters.
  73. //
  74. static void PrintThreadSchedulingInfo(Thread *) {
  75. // NO-OP
  76. }
  77. //--------------------------------------------------------------------------
  78. // Set thread scheduling parameters.  Unfortunately on Linux, there's no
  79. // good way to set this, as Win32Thread_setschedparam is mostly a no-op.
  80. //
  81. static int SetThreadSchedulingParams(Thread *data) {
  82. Thread *thread = static_cast<Thread *>(data);
  83. Win32ThreadPrivateData *pd =
  84. static_cast<Win32ThreadPrivateData *>(thread->_prvData);
  85. int prio = THREAD_PRIORITY_NORMAL;
  86. switch(thread->getSchedulePriority()) {
  87. case Thread::PRIORITY_MAX:
  88. prio = THREAD_PRIORITY_HIGHEST;
  89. break;
  90. case Thread::PRIORITY_HIGH:
  91. prio = THREAD_PRIORITY_ABOVE_NORMAL;
  92. break;
  93. case Thread::PRIORITY_NOMINAL:
  94. prio = THREAD_PRIORITY_NORMAL;
  95. break;   
  96. case Thread::PRIORITY_LOW:
  97. prio = THREAD_PRIORITY_BELOW_NORMAL;
  98. break;       
  99. case Thread::PRIORITY_MIN:
  100. prio = THREAD_PRIORITY_IDLE;
  101. break;   
  102. }
  103. int status = SetThreadPriority( pd->tid , prio);
  104. PrintThreadSchedulingInfo(thread);   
  105. return status!=0;
  106. };
  107. };
  108. };
  109. Thread* Thread::CurrentThread()
  110. {
  111. return (Thread* )TlsGetValue(Win32ThreadPrivateData::TLS.ID);
  112. };
  113. //----------------------------------------------------------------------------
  114. //
  115. // Description: Set the concurrency level (no-op)
  116. //
  117. // Use static public
  118. //
  119. int Thread::SetConcurrency(int) {
  120.     return -1;
  121. };
  122. //----------------------------------------------------------------------------
  123. //
  124. // Description: Get the concurrency level
  125. //
  126. // Use static public
  127. //
  128. int Thread::GetConcurrency() {
  129.     return -1;
  130. };
  131. //----------------------------------------------------------------------------
  132. //
  133. // Decription: Constructor
  134. //
  135. // Use: public.
  136. //
  137. Thread::Thread() {
  138. // there's no need for this
  139. //    if(!s_isInitialized) Init();
  140.     Win32ThreadPrivateData *pd = new Win32ThreadPrivateData();
  141.     pd->stackSize = 0;
  142.     pd->stackSizeLocked = false;
  143.     pd->idSet = false;
  144.     pd->isRunning = false;
  145.     pd->isCanceled = false;
  146. pd->cancelMode = 0;
  147.     pd->uniqueId = 0;
  148.     pd->threadPriority = PRIORITY_DEFAULT;
  149.     pd->threadPolicy = SCHEDULE_DEFAULT;
  150. pd->detached = false; 
  151.     _prvData = static_cast<void *>(pd);
  152. }
  153. //----------------------------------------------------------------------------
  154. //
  155. // Decription: Destructor
  156. //
  157. // Use: public.
  158. //
  159. Thread::~Thread() {
  160.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *>(_prvData);
  161.     if(pd->isRunning) {
  162. pd->cancelMode = 0;
  163. cancel();
  164.     }
  165.     delete pd;
  166. }
  167. //-----------------------------------------------------------------------------
  168. // 
  169. // Description: Initialize Threading
  170. //
  171. // Use: public.
  172. //
  173. void Thread::Init() {
  174. //    if(s_isInitialized) return;
  175. // s_masterThreadPriority = Thread::PRIORITY_DEFAULT;
  176.     s_isInitialized = true;
  177. }
  178. //-----------------------------------------------------------------------------
  179. //
  180. // Description: Get a unique identifier for this thread.
  181. //
  182. // Use: public
  183. //
  184. int Thread::getThreadId() {
  185.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  186.     return pd->uniqueId;
  187. }
  188. //-----------------------------------------------------------------------------
  189. //
  190. // Description: Get the thread's process id
  191. //
  192. // Use: public
  193. //
  194. int Thread::getProcessId() {
  195.     return (int) GetCurrentProcessId();
  196. }
  197. //-----------------------------------------------------------------------------
  198. //
  199. // Description: Determine if the thread is running
  200. //
  201. // Use: public
  202. //
  203. bool Thread::isRunning() {
  204.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  205.     return pd->isRunning;
  206. }
  207. //-----------------------------------------------------------------------------
  208. //
  209. // Description: Start the thread.
  210. //
  211. // Use: public
  212. //
  213. int Thread::start() {
  214.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  215.     //-------------------------------------------------------------------------
  216.     // Prohibit the stack size from being changed.
  217.     //
  218.     pd->stackSizeLocked = true;
  219. unsigned long ID;
  220.     pd->tid = CreateThread(NULL,pd->stackSize,ThreadPrivateActions::StartThread,static_cast<void *>(this),0,&ID);
  221. pd->uniqueId = (int)ID;
  222.     if(pd->tid == INVALID_HANDLE_VALUE) {
  223. return -1;
  224.     }
  225.     pd->idSet = true;
  226.     return 0;
  227. }
  228. int Thread::startThread() 
  229. { return start(); }
  230. //-----------------------------------------------------------------------------
  231. //
  232. // Description: Join the thread.
  233. //
  234. // Use: public
  235. //
  236. int Thread::join() {
  237.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  238. if( pd->detached ) 
  239. return -1; // cannot wait for detached ;
  240. if( WaitForSingleObject(pd->tid,INFINITE) != WAIT_OBJECT_0)
  241. return -1 ;
  242. return 0;
  243. }
  244. int Thread::detach()
  245. {
  246.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  247. pd->detached = true; 
  248. return 0;
  249. }
  250. //-----------------------------------------------------------------------------
  251. //
  252. // Description: Cancel the thread.
  253. //
  254. // Use: public
  255. //
  256. int Thread::cancel() {
  257.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  258. if( pd->cancelMode == 2 )
  259. return -1;
  260. pd->isCanceled = true;
  261. // wait for 5 sec
  262. if( (pd->cancelMode == 1) || WaitForSingleObject(pd->tid, 5000) != WAIT_OBJECT_0)
  263. {
  264. // did not terminate cleanly force termination
  265. return TerminateThread(pd->tid,(DWORD)-1);
  266. }
  267. return 0;
  268. }
  269. int Thread::testCancel()
  270. {
  271.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  272. if(!pd->isCanceled ) return 0;
  273. if(pd->cancelMode == 2)
  274. return 0;
  275. HANDLE curr = GetCurrentThread();
  276. if( pd->tid != curr )
  277. return -1;
  278. ExitThread(0);
  279. return 0;
  280. }
  281. //-----------------------------------------------------------------------------
  282. //
  283. // Description: Disable cancelibility
  284. //
  285. // Use: public
  286. //
  287. int Thread::setCancelModeDisable() {
  288.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  289. pd->cancelMode = 2;
  290. return 0;
  291. }
  292. //-----------------------------------------------------------------------------
  293. //
  294. // Description: set the thread to cancel immediately
  295. //
  296. // Use: public
  297. //
  298. int Thread::setCancelModeAsynchronous() {
  299.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  300. pd->cancelMode  = 1;
  301. return 0;
  302. }
  303. //-----------------------------------------------------------------------------
  304. //
  305. // Description: set the thread to cancel at the next convienent point.
  306. //
  307. // Use: public
  308. //
  309. int Thread::setCancelModeDeferred() {
  310.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  311. pd->cancelMode = 0;
  312.     return 0;
  313. }
  314. //-----------------------------------------------------------------------------
  315. //
  316. // Description: Set the thread's schedule priority (if able)
  317. //
  318. // Use: public
  319. //
  320. int Thread::setSchedulePriority(ThreadPriority priority) {
  321.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  322.     pd->threadPriority = priority;
  323.     if(pd->isRunning) 
  324. return ThreadPrivateActions::SetThreadSchedulingParams(this);
  325.     else 
  326. return 0;
  327. }
  328. //-----------------------------------------------------------------------------
  329. //
  330. // Description: Get the thread's schedule priority (if able)
  331. //
  332. // Use: public
  333. //
  334. int Thread::getSchedulePriority() {
  335.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  336.     return pd->threadPriority;
  337. }
  338. //-----------------------------------------------------------------------------
  339. //
  340. // Description: Set the thread's scheduling policy (if able)
  341. //
  342. // Use: public
  343. //
  344. int Thread::setSchedulePolicy(ThreadPolicy policy) {
  345.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  346.     pd->threadPolicy = policy;
  347.     if(pd->isRunning) 
  348. return ThreadPrivateActions::SetThreadSchedulingParams(this);
  349.     else 
  350. return 0;
  351. }
  352. //-----------------------------------------------------------------------------
  353. //
  354. // Description: Set the thread's scheduling policy (if able)
  355. //
  356. // Use: public
  357. //
  358. int Thread::getSchedulePolicy() {
  359.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  360.     return pd->threadPolicy;
  361. }
  362. //-----------------------------------------------------------------------------
  363. //
  364. // Description: Set the thread's desired stack size
  365. //
  366. // Use: public
  367. //
  368. int Thread::setStackSize(size_t stackSize) {
  369.     Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  370.     if(pd->stackSizeLocked == true) return 13;  // EACESS
  371.     pd->stackSize = stackSize;
  372.     return 0;
  373. }
  374. //-----------------------------------------------------------------------------
  375. //
  376. // Description: Get the thread's stack size.
  377. //
  378. // Use: public
  379. //
  380. size_t Thread::getStackSize() {
  381. Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
  382. return pd->stackSize;
  383. }
  384. //-----------------------------------------------------------------------------
  385. //
  386. // Description:  Print the thread's scheduling information to stdout.
  387. //
  388. // Use: public
  389. //
  390. void Thread::printSchedulingInfo() {
  391.     ThreadPrivateActions::PrintThreadSchedulingInfo(this);
  392. }
  393. //-----------------------------------------------------------------------------
  394. //
  395. // Description:  Yield the processor
  396. //
  397. // Use: protected
  398. //
  399. #if _WIN32_WINNT < 0x0400 // simulate
  400. int SwitchToThread (void)
  401. {
  402. Sleep(10);
  403. return 0;
  404. };
  405. #endif
  406. int Thread::Yield()
  407. {
  408.     return SwitchToThread();
  409. }