Thread.cpp 6.4 KB

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