Thread.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #include "Thread.h"
  2. #include "Globals.h"
  3. using namespace Framework;
  4. // inhalt der Thread Klasse aus Thread.h
  5. // Konstruktor
  6. Thread::Thread()
  7. : ReferenceCounter()
  8. {
  9. threadHandleSys = 0;
  10. threadHandle = 0;
  11. threadId = 0;
  12. thRegister->add( this );
  13. run = 0;
  14. lockCount = 0;
  15. }
  16. // Destruktor
  17. Thread::~Thread()
  18. {
  19. thRegister->remove( this );
  20. #ifdef WIN32
  21. if( threadHandle != 0 && GetCurrentThreadId() == GetThreadId( threadHandle ) )
  22. return;
  23. #else
  24. if( pthread_self() == threadHandle )
  25. return;
  26. #endif
  27. if( run )
  28. warteAufThread( 100000 );
  29. if( run )
  30. ende();
  31. }
  32. // nicht constant
  33. void Thread::start() // startet den Thread
  34. {
  35. if( !run )
  36. {
  37. getThis();
  38. #ifdef WIN32
  39. threadHandle = CreateThread( 0, 0, threadStart, this, 0, &threadId );
  40. #else
  41. pthread_create( &threadHandle, NULL, threadStart, this );
  42. #endif
  43. }
  44. run = 1;
  45. }
  46. #ifdef WIN32
  47. void Thread::pause() // pausiert den Thread
  48. {
  49. if( run )
  50. SuspendThread( threadHandle );
  51. run = 0;
  52. }
  53. void Thread::fortsetzen() // pausiert den Thread
  54. {
  55. if( !run )
  56. ResumeThread( threadHandle );
  57. run = 1;
  58. }
  59. #endif
  60. void Thread::ende() // beendet den Thread
  61. {
  62. if( run )
  63. {
  64. while( lockCount > 0 )
  65. Sleep( 100 );
  66. bool rel = run;
  67. #ifdef WIN32
  68. #pragma warning(suppress: 6258)
  69. TerminateThread( threadHandle, 0 );
  70. #else
  71. if( pthread_self() == threadHandle )
  72. {
  73. thRegister->addClosedThread( threadHandle );
  74. run = 0;
  75. }
  76. pthread_cancel( threadHandle );
  77. #endif
  78. if( rel )
  79. {
  80. run = 0;
  81. release();
  82. return;
  83. }
  84. }
  85. run = 0;
  86. }
  87. void Thread::thread() // Thread
  88. {}
  89. void Thread::threadEnd()
  90. {
  91. run = 0;
  92. release();
  93. }
  94. // constant
  95. bool Thread::isRunning() const // prüft, ob der Thrad aktiv ist
  96. {
  97. return run;
  98. }
  99. int Thread::warteAufThread( int zeit ) // wartet zeit lang auf den Thread
  100. {
  101. #ifdef WIN32
  102. if( !run )
  103. return WAIT_OBJECT_0;
  104. if( GetCurrentThreadId() == GetThreadId( threadHandle ) )
  105. return WAIT_OBJECT_0;
  106. return WaitForSingleObject( threadHandle, zeit );
  107. #else
  108. if( !run )
  109. return 0;
  110. if( pthread_self() == threadHandle )
  111. return 0;
  112. timespec ts;
  113. ts.tv_sec = 0;
  114. ts.tv_nsec = 1000 * zeit;
  115. if( threadHandleSys )
  116. *threadHandleSys = 0;
  117. int ret = pthread_timedjoin_np( threadHandle, 0, &ts );
  118. if( !ret )
  119. threadHandle = 0;
  120. else
  121. *threadHandleSys = threadHandle;
  122. return ret;
  123. #endif
  124. }
  125. // Legt einen Frameworkpointer auf ein Threadhandle fest, der auf 0 gesetzt wird, falls die Ressourcen des Threads bereits follstänfig aufgeräumt wurden
  126. // ths: Ein Zeiger auf ein Threadhandle, das verändert werden soll
  127. void Thread::setSystemHandlePointer( pthread_t *ths )
  128. {
  129. threadHandleSys = ths;
  130. *threadHandleSys = threadHandle;
  131. }
  132. pthread_t Thread::getThreadHandle() const
  133. {
  134. return threadHandle;
  135. }
  136. void Thread::addCriticalLock()
  137. {
  138. lockCount++;
  139. }
  140. void Thread::removeCriticalLock()
  141. {
  142. lockCount--;
  143. }
  144. // funktionen
  145. #ifdef WIN32
  146. unsigned long __stdcall Framework::threadStart( void *param )
  147. {
  148. if( istThreadOk( (Thread *)param ) )
  149. ( (Thread *)param )->thread();
  150. if( istThreadOk( (Thread *)param ) )
  151. ( (Thread *)param )->threadEnd();
  152. return 0;
  153. }
  154. #else
  155. void *Framework::threadStart( void *param )
  156. {
  157. pthread_t handle = 0;
  158. pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, 0 );
  159. if( istThreadOk( (Thread *)param ) )
  160. {
  161. ( (Thread *)param )->setSystemHandlePointer( &handle );
  162. ( (Thread *)param )->thread();
  163. }
  164. if( istThreadOk( (Thread *)param ) )
  165. ( (Thread *)param )->threadEnd();
  166. thRegister->addClosedThread( handle );
  167. pthread_exit( 0 );
  168. return 0;
  169. }
  170. #endif
  171. // Konstruktor
  172. ThreadRegister::ThreadRegister()
  173. {
  174. InitializeCriticalSection( &cs );
  175. }
  176. // Destruktor
  177. ThreadRegister::~ThreadRegister()
  178. {
  179. EnterCriticalSection( &cs );
  180. while( threads.hat( 0 ) )
  181. {
  182. LeaveCriticalSection( &cs );
  183. Sleep( 1000 ); // wait until all threads are done
  184. EnterCriticalSection( &cs );
  185. }
  186. cleanUpClosedThreads();
  187. LeaveCriticalSection( &cs );
  188. DeleteCriticalSection( &cs );
  189. }
  190. // Inhalt der ThreadRegister Klasse aus Thread.h
  191. void ThreadRegister::add( Thread *t )
  192. {
  193. EnterCriticalSection( &cs );
  194. threads.add( t );
  195. LeaveCriticalSection( &cs );
  196. }
  197. void ThreadRegister::remove( Thread *t )
  198. {
  199. EnterCriticalSection( &cs );
  200. threads.remove( threads.getWertIndex( t ) );
  201. LeaveCriticalSection( &cs );
  202. }
  203. bool ThreadRegister::isThread( Thread *t )
  204. {
  205. EnterCriticalSection( &cs );
  206. bool ret = threads.hat( threads.getWertIndex( t ) );
  207. LeaveCriticalSection( &cs );
  208. return ret;
  209. }
  210. void ThreadRegister::addClosedThread( pthread_t handle )
  211. {
  212. EnterCriticalSection( &cs );
  213. if( handle )
  214. closedThreads.add( handle );
  215. LeaveCriticalSection( &cs );
  216. }
  217. // Sucht nach einem bestimmten Thread und gibt das zugehörige Objekt zurück
  218. // handle: Ein handle zu dem gesuchten Thread
  219. Thread *ThreadRegister::zThread( pthread_t handle )
  220. {
  221. EnterCriticalSection( &cs );
  222. for( auto i : threads )
  223. {
  224. if( i->getThreadHandle() && GetThreadId( i->getThreadHandle() ) == GetThreadId( handle ) && GetThreadId( handle ) != 0 )
  225. {
  226. LeaveCriticalSection( &cs );
  227. return i;
  228. }
  229. }
  230. LeaveCriticalSection( &cs );
  231. return 0;
  232. }
  233. // sperrt das register
  234. void ThreadRegister::lock()
  235. {
  236. EnterCriticalSection( &cs );
  237. }
  238. // entsperrt das register
  239. void ThreadRegister::unlock()
  240. {
  241. LeaveCriticalSection( &cs );
  242. }
  243. // Löscht die bereits beendetetn Threads und gibt ihre Reccourcen wieder frei
  244. void ThreadRegister::cleanUpClosedThreads()
  245. {
  246. EnterCriticalSection( &cs );
  247. while( closedThreads.getEintragAnzahl() > 0 )
  248. {
  249. #ifndef WIN32
  250. pthread_join( closedThreads.get( 0 ), 0 );
  251. #endif
  252. closedThreads.remove( 0 );
  253. }
  254. LeaveCriticalSection( &cs );
  255. }