Thread.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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 > 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. release();
  92. }
  93. // constant
  94. bool Thread::isRunning() const // checks if the thread is active
  95. {
  96. return run;
  97. }
  98. int Thread::waitForThread(int zeit) // waits for the thread for the given time
  99. {
  100. #ifdef WIN32
  101. if (!run) return WAIT_OBJECT_0;
  102. if (GetCurrentThreadId() == GetThreadId(threadHandle)) return WAIT_OBJECT_0;
  103. return WaitForSingleObject(threadHandle, zeit);
  104. #else
  105. if (!run) return 0;
  106. if (pthread_self() == threadHandle) return 0;
  107. timespec ts;
  108. if (clock_gettime(CLOCK_REALTIME, &ts) == -1) return -1;
  109. ts.tv_sec += (zeit + ts.tv_nsec / 1000) / 1000;
  110. ts.tv_nsec = 1000 * ((zeit + ts.tv_nsec / 1000) % 1000);
  111. if (threadHandleSys) *threadHandleSys = 0;
  112. int ret = pthread_timedjoin_np(threadHandle, 0, &ts);
  113. if (!ret)
  114. threadHandle = 0;
  115. else
  116. *threadHandleSys = threadHandle;
  117. return ret;
  118. #endif
  119. }
  120. // Sets a framework pointer to a thread handle that is set to 0
  121. // when the thread's resources have already been fully cleaned up
  122. // ths: A pointer to a thread handle that should be modified
  123. void Thread::setSystemHandlePointer(pthread_t* ths)
  124. {
  125. threadHandleSys = ths;
  126. *threadHandleSys = threadHandle;
  127. }
  128. pthread_t Thread::getThreadHandle() const
  129. {
  130. return threadHandle;
  131. }
  132. // set the name of the thread
  133. void Thread::setName(const char* name)
  134. {
  135. this->name = name;
  136. }
  137. // get the name of the thread
  138. const char* Thread::getName() const
  139. {
  140. return name ? name : typeid(*this).name();
  141. }
  142. void Thread::addCriticalLock()
  143. {
  144. lockCount++;
  145. }
  146. void Thread::removeCriticalLock()
  147. {
  148. lockCount--;
  149. }
  150. // functions
  151. #ifdef WIN32
  152. unsigned long __stdcall Framework::threadStart(void* param)
  153. {
  154. currentThreadId = GetCurrentThreadId();
  155. if (isThreadOk((Thread*)param))
  156. {
  157. const char* name = ((Thread*)param)->getName();
  158. wchar_t* wc = new wchar_t[textLength(name) + 1];
  159. size_t l;
  160. mbstowcs_s(&l, wc, textLength(name) + 1, name, textLength(name));
  161. SetThreadDescription(((Thread*)param)->getThreadHandle(), wc);
  162. delete[] wc;
  163. ((Thread*)param)->thread();
  164. }
  165. if (isThreadOk((Thread*)param)) ((Thread*)param)->threadEnd();
  166. return 0;
  167. }
  168. #else
  169. void* Framework::threadStart(void* param)
  170. {
  171. currentThreadId = gettid();
  172. pthread_t handle = 0;
  173. pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
  174. if (isThreadOk((Thread*)param))
  175. {
  176. pthread_setname_np(
  177. ((Thread*)param)->getThreadHandle(), ((Thread*)param)->getName());
  178. ((Thread*)param)->setSystemHandlePointer(&handle);
  179. ((Thread*)param)->thread();
  180. }
  181. if (isThreadOk((Thread*)param)) ((Thread*)param)->threadEnd();
  182. thRegister->addClosedThread(handle);
  183. pthread_exit(0);
  184. return 0;
  185. }
  186. #endif
  187. // Constructor
  188. ThreadRegister::ThreadRegister()
  189. {
  190. InitializeCriticalSection(&cs);
  191. }
  192. // Destructor
  193. ThreadRegister::~ThreadRegister()
  194. {
  195. EnterCriticalSection(&cs);
  196. while (threads.has(0))
  197. {
  198. LeaveCriticalSection(&cs);
  199. Sleep(1000); // wait until all threads are done
  200. EnterCriticalSection(&cs);
  201. }
  202. cleanUpClosedThreads();
  203. LeaveCriticalSection(&cs);
  204. DeleteCriticalSection(&cs);
  205. }
  206. // Contents of the ThreadRegister class from Thread.h
  207. void ThreadRegister::add(Thread* t)
  208. {
  209. EnterCriticalSection(&cs);
  210. threads.add(t);
  211. LeaveCriticalSection(&cs);
  212. }
  213. void ThreadRegister::remove(Thread* t)
  214. {
  215. EnterCriticalSection(&cs);
  216. threads.remove(threads.getValueIndex(t));
  217. LeaveCriticalSection(&cs);
  218. }
  219. bool ThreadRegister::isThread(Thread* t)
  220. {
  221. EnterCriticalSection(&cs);
  222. bool ret = threads.has(threads.getValueIndex(t));
  223. LeaveCriticalSection(&cs);
  224. return ret;
  225. }
  226. void ThreadRegister::addClosedThread(pthread_t handle)
  227. {
  228. EnterCriticalSection(&cs);
  229. if (handle) closedThreads.add(handle);
  230. LeaveCriticalSection(&cs);
  231. }
  232. // Searches for a specific thread and returns the associated object
  233. // handle: A handle to the thread being searched for
  234. Thread* ThreadRegister::zThread(pthread_t handle)
  235. {
  236. if (handle == 0) return 0;
  237. EnterCriticalSection(&cs);
  238. for (auto i : threads)
  239. {
  240. if (i->getThreadHandle() && i->getThreadHandle() == handle)
  241. {
  242. LeaveCriticalSection(&cs);
  243. return i;
  244. }
  245. }
  246. LeaveCriticalSection(&cs);
  247. return 0;
  248. }
  249. // locks the register
  250. void ThreadRegister::lock()
  251. {
  252. EnterCriticalSection(&cs);
  253. }
  254. // unlocks the register
  255. void ThreadRegister::unlock()
  256. {
  257. LeaveCriticalSection(&cs);
  258. }
  259. // Deletes already finished threads and releases their resources
  260. void ThreadRegister::cleanUpClosedThreads()
  261. {
  262. EnterCriticalSection(&cs);
  263. while (closedThreads.getEntryCount() > 0)
  264. {
  265. #ifndef WIN32
  266. pthread_join(closedThreads.get(0), 0);
  267. #endif
  268. closedThreads.remove(0);
  269. }
  270. LeaveCriticalSection(&cs);
  271. }