Thread.cpp 6.5 KB

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