jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

269 lines
6.4KB

  1. /*
  2. Copyright (C) 2001 Paul Davis
  3. Copyright (C) 2004-2006 Grame
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include "JackWinThread.h"
  17. #include "JackError.h"
  18. #include <assert.h>
  19. namespace Jack
  20. {
  21. DWORD WINAPI JackWinThread::ThreadHandler(void* arg)
  22. {
  23. JackWinThread* obj = (JackWinThread*)arg;
  24. JackRunnableInterface* runnable = obj->fRunnable;
  25. // Call Init method
  26. if (!runnable->Init()) {
  27. jack_error("Thread init fails: thread quits");
  28. return 0;
  29. }
  30. // TODO: Signal creation thread when started with StartSync
  31. /*
  32. if (!obj->fRunning) {
  33. obj->fRunning = true;
  34. SetEvent(obj->fEvent);
  35. }
  36. */
  37. jack_log("ThreadHandler: start");
  38. obj->fStatus = kRunning;
  39. // If Init succeed, start the thread loop
  40. bool res = true;
  41. while (obj->fStatus == kRunning && res) {
  42. res = runnable->Execute();
  43. }
  44. SetEvent(obj->fEvent);
  45. jack_log("ThreadHandler: exit");
  46. return 0;
  47. }
  48. JackWinThread::JackWinThread(JackRunnableInterface* runnable)
  49. : JackThread(runnable, 0, false, 0)
  50. {
  51. fEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  52. fThread = NULL;
  53. assert(fEvent);
  54. }
  55. JackWinThread::~JackWinThread()
  56. {
  57. CloseHandle(fEvent);
  58. }
  59. int JackWinThread::Start()
  60. {
  61. fEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  62. if (fEvent == NULL) {
  63. jack_error("Cannot create event error = %d", GetLastError());
  64. return -1;
  65. }
  66. fStatus = kStarting;
  67. // Check if the thread was correctly started
  68. if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) {
  69. fStatus = kIdle;
  70. return -1;
  71. } else {
  72. return 0;
  73. }
  74. }
  75. int JackWinThread::StartImp(pthread_t* thread, int priority, int realtime, ThreadCallback start_routine, void* arg)
  76. {
  77. DWORD id;
  78. if (realtime) {
  79. jack_log("Create RT thread");
  80. *thread = CreateThread(NULL, 0, start_routine, arg, 0, &id);
  81. if (*thread == NULL) {
  82. jack_error("Cannot create thread error = %d", GetLastError());
  83. return -1;
  84. }
  85. if (!SetThreadPriority(*thread, THREAD_PRIORITY_TIME_CRITICAL)) {
  86. jack_error("Cannot set priority class = %d", GetLastError());
  87. return -1;
  88. }
  89. return 0;
  90. } else {
  91. jack_log("Create non RT thread");
  92. *thread = CreateThread(NULL, 0, start_routine, arg, 0, &id);
  93. if (thread == NULL) {
  94. jack_error("Cannot create thread error = %d", GetLastError());
  95. return -1;
  96. }
  97. return 0;
  98. }
  99. }
  100. int JackWinThread::StartSync()
  101. {
  102. jack_error("Not implemented yet");
  103. return -1;
  104. /*
  105. DWORD id;
  106. fEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  107. if (fEvent == NULL) {
  108. jack_error("Cannot create event error = %d", GetLastError());
  109. return -1;
  110. }
  111. fStatus = kStarting;
  112. if (fRealTime) {
  113. jack_log("Create RT thread");
  114. fThread = CreateThread(NULL, 0, ThreadHandler, (void*)this, 0, &id);
  115. if (fThread == NULL) {
  116. jack_error("Cannot create thread error = %d", GetLastError());
  117. return -1;
  118. }
  119. if (WaitForSingleObject(fEvent, 3000) != WAIT_OBJECT_0) { // wait 3 sec
  120. jack_error("Thread has not started");
  121. return -1;
  122. }
  123. if (!SetThreadPriority(fThread, THREAD_PRIORITY_TIME_CRITICAL)) {
  124. jack_error("Cannot set priority class = %d", GetLastError());
  125. return -1;
  126. }
  127. return 0;
  128. } else {
  129. jack_log("Create non RT thread");
  130. fThread = CreateThread(NULL, 0, ThreadHandler, (void*)this, 0, &id);
  131. if (fThread == NULL) {
  132. jack_error("Cannot create thread error = %d", GetLastError());
  133. return -1;
  134. }
  135. if (WaitForSingleObject(fEvent, 3000) != WAIT_OBJECT_0) { // wait 3 sec
  136. jack_error("Thread has not started");
  137. return -1;
  138. }
  139. return 0;
  140. }
  141. */
  142. }
  143. // voir http://www.microsoft.com/belux/msdn/nl/community/columns/ldoc/multithread1.mspx
  144. int JackWinThread::Kill()
  145. {
  146. if (fThread) { // If thread has been started
  147. TerminateThread(fThread, 0);
  148. WaitForSingleObject(fThread, INFINITE);
  149. CloseHandle(fThread);
  150. jack_log("JackWinThread::Kill");
  151. fThread = NULL;
  152. fStatus = kIdle;
  153. return 0;
  154. } else {
  155. return -1;
  156. }
  157. }
  158. int JackWinThread::Stop()
  159. {
  160. if (fThread) { // If thread has been started
  161. jack_log("JackWinThread::Stop");
  162. fStatus = kIdle; // Request for the thread to stop
  163. WaitForSingleObject(fEvent, INFINITE);
  164. CloseHandle(fThread);
  165. fThread = NULL;
  166. return 0;
  167. } else {
  168. return -1;
  169. }
  170. }
  171. int JackWinThread::AcquireRealTime()
  172. {
  173. return (fThread) ? AcquireRealTimeImp(fThread, fPriority) : -1;
  174. }
  175. int JackWinThread::AcquireRealTime(int priority)
  176. {
  177. fPriority = priority;
  178. return AcquireRealTime();
  179. }
  180. int JackWinThread::AcquireRealTimeImp(pthread_t thread, int priority)
  181. {
  182. jack_log("JackWinThread::AcquireRealTime");
  183. if (SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL)) {
  184. jack_log("JackWinThread::AcquireRealTime OK");
  185. return 0;
  186. } else {
  187. jack_error("Cannot set thread priority = %d", GetLastError());
  188. return -1;
  189. }
  190. }
  191. int JackWinThread::DropRealTime()
  192. {
  193. return DropRealTimeImp(fThread);
  194. }
  195. int JackWinThread::DropRealTimeImp(pthread_t thread)
  196. {
  197. if (SetThreadPriority(thread, THREAD_PRIORITY_NORMAL)) {
  198. return 0;
  199. } else {
  200. jack_error("Cannot set thread priority = %d", GetLastError());
  201. return -1;
  202. }
  203. }
  204. pthread_t JackWinThread::GetThreadID()
  205. {
  206. return fThread;
  207. }
  208. void JackWinThread::Terminate()
  209. {
  210. TerminateThread(fThread, 0);
  211. WaitForSingleObject(fThread, INFINITE);
  212. CloseHandle(fThread);
  213. }
  214. } // end of namespace