ThreadWindows.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // Copyright (C) 2014, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include "anki/util/Thread.h"
  6. #include <windows.h>
  7. namespace anki {
  8. //==============================================================================
  9. // Thread =
  10. //==============================================================================
  11. //==============================================================================
  12. static DWORD WINAPI threadCallback(LPVOID ud)
  13. {
  14. ANKI_ASSERT(ud != nullptr);
  15. Thread* thread = reinterpret_cast<Thread*>(ud);
  16. // Set thread name
  17. if(thread->_getName()[0] != '\0')
  18. {
  19. // TODO
  20. }
  21. // Call the callback
  22. Thread::Info info;
  23. info.m_userData = thread->_getUserData();
  24. info.m_threadName = thread->_getName();
  25. I err = thread->_getCallback()(info);
  26. return err;
  27. }
  28. //==============================================================================
  29. Thread::Thread(const char* name)
  30. {
  31. // Init the name
  32. if(name)
  33. {
  34. U len = std::strlen(name);
  35. len = std::min<U>(len, sizeof(m_name) - 1);
  36. std::memcpy(&m_name[0], &name[0], len);
  37. m_name[len] = '\0';
  38. }
  39. else
  40. {
  41. m_name[0] = '\0';
  42. }
  43. }
  44. //==============================================================================
  45. Thread::~Thread()
  46. {
  47. ANKI_ASSERT(!m_started && "Thread probably not joined");
  48. free(m_impl);
  49. m_impl = nullptr;
  50. }
  51. //==============================================================================
  52. void Thread::start(void* userData, Callback callback)
  53. {
  54. ANKI_ASSERT(!m_started);
  55. ANKI_ASSERT(callback != nullptr);
  56. m_callback = callback;
  57. m_userData = userData;
  58. m_impl = CreateThread(nullptr, 0, threadCallback, this, 0, nullptr);
  59. if(m_impl == nullptr)
  60. {
  61. throw ANKI_EXCEPTION("CreateThread() failed");
  62. }
  63. else
  64. {
  65. #if ANKI_ASSERTIONS
  66. m_started = true;
  67. #endif
  68. }
  69. }
  70. //==============================================================================
  71. I Thread::join()
  72. {
  73. ANKI_ASSERT(m_started);
  74. // Wait thread
  75. WaitForSingleObject(m_impl, INFINITE);
  76. // Get return code
  77. DWORD exitCode = 0;
  78. ok = GetExitCodeThread(m_impl, &exitCode);
  79. if(!ok)
  80. {
  81. throw ANKI_EXCEPTION("GetExitCodeThread() failed");
  82. }
  83. // Delete handle
  84. BOOL ok = CloseHandle(m_impl);
  85. if(!ok)
  86. {
  87. throw ANKI_EXCEPTION("CloseHandle() failed");
  88. }
  89. return exitCode;
  90. }
  91. //==============================================================================
  92. Thread::Id Thread::getCurrentThreadId()
  93. {
  94. HANDLE x = GetCurrentThread();
  95. return x;
  96. }
  97. //==============================================================================
  98. // Mutex =
  99. //==============================================================================
  100. //==============================================================================
  101. Mutex::Mutex()
  102. {
  103. CRITICAL_SECTION* mtx =
  104. reinterpret_cast<CRITICAL_SECTION*>(malloc(sizeof(CRITICAL_SECTION)));
  105. if(mtx == nullptr)
  106. {
  107. throw ANKI_EXCEPTION("Out of memory");
  108. }
  109. m_impl = mtx;
  110. BOOL ok = InitializeCriticalSectionAndSpinCount(mtx, 0x400);
  111. if(!ok)
  112. {
  113. free(m_impl);
  114. m_impl = nullptr;
  115. throw ANKI_EXCEPTION("InitializeCriticalSectionAndSpinCount() failed");
  116. }
  117. }
  118. //==============================================================================
  119. Mutex::~Mutex()
  120. {
  121. CRITICAL_SECTION* mtx = reinterpret_cast<CRITICAL_SECTION*>(m_impl);
  122. DeleteCriticalSection(mtx);
  123. free(m_impl);
  124. m_impl = nullptr;
  125. }
  126. //==============================================================================
  127. void Mutex::lock()
  128. {
  129. CRITICAL_SECTION* mtx = reinterpret_cast<CRITICAL_SECTION*>(m_impl);
  130. EnterCriticalSection(mtx);
  131. }
  132. //==============================================================================
  133. Bool Mutex::tryLock()
  134. {
  135. CRITICAL_SECTION* mtx = reinterpret_cast<CRITICAL_SECTION*>(m_impl);
  136. BOOL enter = EnterCriticalSection(mtx);
  137. return enter;
  138. }
  139. //==============================================================================
  140. void Mutex::unlock()
  141. {
  142. CRITICAL_SECTION* mtx = reinterpret_cast<CRITICAL_SECTION*>(m_impl);
  143. LeaveCriticalSection(mtx);
  144. }
  145. //==============================================================================
  146. // ConditionVariable =
  147. //==============================================================================
  148. //==============================================================================
  149. ConditionVariable::ConditionVariable()
  150. {
  151. CONDITION_VARIABLE* cond = reinterpret_cast<CONDITION_VARIABLE*>(
  152. malloc(sizeof(CONDITION_VARIABLE)));
  153. if(cond == nullptr)
  154. {
  155. throw ANKI_EXCEPTION("Out of memory");
  156. }
  157. m_impl = cond;
  158. InitializeConditionVariable(cond);
  159. }
  160. //==============================================================================
  161. ConditionVariable::~ConditionVariable()
  162. {
  163. free(m_impl);
  164. m_impl = nullptr;
  165. }
  166. //==============================================================================
  167. void ConditionVariable::notifyOne()
  168. {
  169. CONDITION_VARIABLE* cond = reinterpret_cast<CONDITION_VARIABLE*>(m_impl);
  170. WakeConditionVariable(cond);
  171. }
  172. //==============================================================================
  173. void ConditionVariable::notifyAll()
  174. {
  175. CONDITION_VARIABLE* cond = reinterpret_cast<CONDITION_VARIABLE*>(m_impl);
  176. WakeAllConditionVariable(cond);
  177. }
  178. //==============================================================================
  179. void ConditionVariable::wait(Mutex& amtx)
  180. {
  181. CONDITION_VARIABLE* cond = reinterpret_cast<CONDITION_VARIABLE*>(m_impl);
  182. CRITICAL_SECTION* mtx = reinterpret_cast<CRITICAL_SECTION*>(m_impl);
  183. SleepConditionVariableCS(cond, INFINITE);
  184. }
  185. } // end namespace anki