Thread.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. #include "Thread.h"
  2. #include "Globals.h"
  3. #ifndef WIN32
  4. # include <unistd.h>
  5. #endif
  6. using namespace Framework;
  7. // Contents of the Thread class from Thread.h
  8. // Constructor
  9. Thread::Thread()
  10. : ReferenceCounter()
  11. {
  12. threadHandleSys = 0;
  13. threadHandle = 0;
  14. threadId = 0;
  15. thRegister->add(this);
  16. run = 0;
  17. lockCount = 0;
  18. name = 0;
  19. }
  20. // Destructor
  21. Thread::~Thread()
  22. {
  23. thRegister->remove(this);
  24. #ifdef WIN32
  25. if (threadHandle != 0 && GetCurrentThreadId() == GetThreadId(threadHandle))
  26. return;
  27. #else
  28. if (pthread_self() == threadHandle) return;
  29. #endif
  30. if (run) waitForThread(100000);
  31. if (run) ende();
  32. }
  33. // non-constant
  34. void Thread::start() // starts the 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() // pauses the thread
  49. {
  50. if (run) SuspendThread(threadHandle);
  51. run = 0;
  52. }
  53. void Thread::resume() // resumes the thread
  54. {
  55. if (!run) ResumeThread(threadHandle);
  56. run = 1;
  57. }
  58. #endif
  59. void Thread::ende() // terminates the thread
  60. {
  61. if (run)
  62. {
  63. while (lockCount && *lockCount > 0)
  64. Sleep(100);
  65. bool rel = run;
  66. #ifdef WIN32
  67. # pragma warning(suppress : 6258)
  68. TerminateThread(threadHandle, 0);
  69. #else
  70. if (pthread_self() == threadHandle)
  71. {
  72. thRegister->addClosedThread(threadHandle);
  73. run = 0;
  74. }
  75. pthread_cancel(threadHandle);
  76. #endif
  77. if (rel)
  78. {
  79. run = 0;
  80. release();
  81. return;
  82. }
  83. }
  84. run = 0;
  85. }
  86. void Thread::thread() // Thread
  87. {}
  88. void Thread::threadEnd()
  89. {
  90. run = 0;
  91. lockCount = 0;
  92. release();
  93. }
  94. // constant
  95. bool Thread::isRunning() const // checks if the thread is active
  96. {
  97. return run;
  98. }
  99. int Thread::waitForThread(int zeit) // waits for the thread for the given time
  100. {
  101. #ifdef WIN32
  102. if (!run) return WAIT_OBJECT_0;
  103. if (GetCurrentThreadId() == GetThreadId(threadHandle)) return WAIT_OBJECT_0;
  104. return WaitForSingleObject(threadHandle, zeit);
  105. #else
  106. if (!run) return 0;
  107. if (pthread_self() == threadHandle) return 0;
  108. timespec ts;
  109. if (clock_gettime(CLOCK_REALTIME, &ts) == -1) return -1;
  110. ts.tv_sec += (zeit + ts.tv_nsec / 1000) / 1000;
  111. ts.tv_nsec = 1000 * ((zeit + ts.tv_nsec / 1000) % 1000);
  112. if (threadHandleSys) *threadHandleSys = 0;
  113. int ret = pthread_timedjoin_np(threadHandle, 0, &ts);
  114. if (!ret)
  115. threadHandle = 0;
  116. else
  117. *threadHandleSys = threadHandle;
  118. return ret;
  119. #endif
  120. }
  121. // Sets a framework pointer to a thread handle that is set to 0
  122. // when the thread's resources have already been fully cleaned up
  123. // ths: A pointer to a thread handle that should be modified
  124. void Thread::setSystemHandlePointer(pthread_t* ths)
  125. {
  126. threadHandleSys = ths;
  127. *threadHandleSys = threadHandle;
  128. }
  129. pthread_t Thread::getThreadHandle() const
  130. {
  131. return threadHandle;
  132. }
  133. // set the name of the thread
  134. void Thread::setName(const char* name)
  135. {
  136. this->name = name;
  137. }
  138. // get the name of the thread
  139. const char* Thread::getName() const
  140. {
  141. return name ? name : typeid(*this).name();
  142. }
  143. void Thread::setLockCount(int* lockCount)
  144. {
  145. this->lockCount = lockCount;
  146. }
  147. // functions
  148. #ifdef WIN32
  149. unsigned long __stdcall Framework::threadStart(void* param)
  150. {
  151. currentThreadId = GetCurrentThreadId();
  152. if (isThreadOk((Thread*)param))
  153. {
  154. ((Thread*)param)->setLockCount(&currentThreadLockCount);
  155. const char* name = ((Thread*)param)->getName();
  156. wchar_t* wc = new wchar_t[textLength(name) + 1];
  157. size_t l;
  158. mbstowcs_s(&l, wc, textLength(name) + 1, name, textLength(name));
  159. SetThreadDescription(((Thread*)param)->getThreadHandle(), wc);
  160. delete[] wc;
  161. ((Thread*)param)->thread();
  162. }
  163. if (isThreadOk((Thread*)param)) ((Thread*)param)->threadEnd();
  164. return 0;
  165. }
  166. #else
  167. void* Framework::threadStart(void* param)
  168. {
  169. currentThreadId = gettid();
  170. pthread_t handle = 0;
  171. pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
  172. if (isThreadOk((Thread*)param))
  173. {
  174. ((Thread*)param)->setLockCount(&currentThreadLockCount);
  175. pthread_setname_np(
  176. ((Thread*)param)->getThreadHandle(), ((Thread*)param)->getName());
  177. ((Thread*)param)->setSystemHandlePointer(&handle);
  178. ((Thread*)param)->thread();
  179. }
  180. if (isThreadOk((Thread*)param)) ((Thread*)param)->threadEnd();
  181. thRegister->addClosedThread(handle);
  182. pthread_exit(0);
  183. return 0;
  184. }
  185. #endif
  186. // Constructor
  187. ThreadRegister::ThreadRegister()
  188. {
  189. InitializeCriticalSection(&cs);
  190. }
  191. // Destructor
  192. ThreadRegister::~ThreadRegister()
  193. {
  194. EnterCriticalSection(&cs);
  195. while (threads.has(0))
  196. {
  197. LeaveCriticalSection(&cs);
  198. Sleep(1000); // wait until all threads are done
  199. EnterCriticalSection(&cs);
  200. }
  201. cleanUpClosedThreads();
  202. LeaveCriticalSection(&cs);
  203. DeleteCriticalSection(&cs);
  204. }
  205. // Contents of the ThreadRegister class from Thread.h
  206. void ThreadRegister::add(Thread* t)
  207. {
  208. EnterCriticalSection(&cs);
  209. threads.add(t);
  210. LeaveCriticalSection(&cs);
  211. }
  212. void ThreadRegister::remove(Thread* t)
  213. {
  214. EnterCriticalSection(&cs);
  215. threads.remove(threads.getValueIndex(t));
  216. LeaveCriticalSection(&cs);
  217. }
  218. bool ThreadRegister::isThread(Thread* t)
  219. {
  220. EnterCriticalSection(&cs);
  221. bool ret = threads.has(threads.getValueIndex(t));
  222. LeaveCriticalSection(&cs);
  223. return ret;
  224. }
  225. void ThreadRegister::addClosedThread(pthread_t handle)
  226. {
  227. EnterCriticalSection(&cs);
  228. if (handle) closedThreads.add(handle);
  229. LeaveCriticalSection(&cs);
  230. }
  231. // Searches for a specific thread and returns the associated object
  232. // handle: A handle to the thread being searched for
  233. Thread* ThreadRegister::zThread(pthread_t handle)
  234. {
  235. if (handle == 0) return 0;
  236. EnterCriticalSection(&cs);
  237. for (auto i : threads)
  238. {
  239. if (i->getThreadHandle() && i->getThreadHandle() == handle)
  240. {
  241. LeaveCriticalSection(&cs);
  242. return i;
  243. }
  244. }
  245. LeaveCriticalSection(&cs);
  246. return 0;
  247. }
  248. // locks the register
  249. void ThreadRegister::lock()
  250. {
  251. EnterCriticalSection(&cs);
  252. }
  253. // unlocks the register
  254. void ThreadRegister::unlock()
  255. {
  256. LeaveCriticalSection(&cs);
  257. }
  258. // Deletes already finished threads and releases their resources
  259. void ThreadRegister::cleanUpClosedThreads()
  260. {
  261. EnterCriticalSection(&cs);
  262. while (closedThreads.getEntryCount() > 0)
  263. {
  264. #ifndef WIN32
  265. pthread_join(closedThreads.get(0), 0);
  266. #endif
  267. closedThreads.remove(0);
  268. }
  269. LeaveCriticalSection(&cs);
  270. }