Jack2
1.9.8
|
00001 /* 00002 Copyright (C) 2004-2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU Lesser General Public License as published by 00006 the Free Software Foundation; either version 2.1 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 00018 */ 00019 00020 #include "JackWinThread.h" 00021 #include "JackError.h" 00022 #include "JackTime.h" 00023 #include <assert.h> 00024 #include <stdio.h> 00025 00026 namespace Jack 00027 { 00028 00029 DWORD WINAPI JackWinThread::ThreadHandler(void* arg) 00030 { 00031 JackWinThread* obj = (JackWinThread*)arg; 00032 JackRunnableInterface* runnable = obj->fRunnable; 00033 00034 // Signal creation thread when started with StartSync 00035 jack_log("ThreadHandler: start"); 00036 obj->fStatus = kIniting; 00037 00038 // Call Init method 00039 if (!runnable->Init()) { 00040 jack_error("Thread init fails: thread quits"); 00041 return 0; 00042 } 00043 00044 obj->fStatus = kRunning; 00045 00046 // If Init succeed, start the thread loop 00047 bool res = true; 00048 while (obj->fStatus == kRunning && res) { 00049 res = runnable->Execute(); 00050 } 00051 00052 SetEvent(obj->fEvent); 00053 jack_log("ThreadHandler: exit"); 00054 return 0; 00055 } 00056 00057 JackWinThread::JackWinThread(JackRunnableInterface* runnable) 00058 : JackMMCSS(), JackThreadInterface(runnable, 0, false, 0) 00059 { 00060 fEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 00061 fThread = (HANDLE)NULL; 00062 assert(fEvent); 00063 } 00064 00065 JackWinThread::~JackWinThread() 00066 { 00067 CloseHandle(fEvent); 00068 CloseHandle(fThread); 00069 } 00070 00071 int JackWinThread::Start() 00072 { 00073 fStatus = kStarting; 00074 00075 // Check if the thread was correctly started 00076 if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { 00077 fStatus = kIdle; 00078 return -1; 00079 } else { 00080 return 0; 00081 } 00082 } 00083 00084 int JackWinThread::StartSync() 00085 { 00086 fStatus = kStarting; 00087 00088 if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { 00089 fStatus = kIdle; 00090 return -1; 00091 } else { 00092 int count = 0; 00093 while (fStatus == kStarting && ++count < 1000) { 00094 JackSleep(1000); 00095 } 00096 return (count == 1000) ? -1 : 0; 00097 } 00098 } 00099 00100 int JackWinThread::StartImp(jack_native_thread_t* thread, int priority, int realtime, ThreadCallback start_routine, void* arg) 00101 { 00102 DWORD id; 00103 *thread = CreateThread(NULL, 0, start_routine, arg, 0, &id); 00104 00105 if (*thread == NULL) { 00106 jack_error("Cannot create thread error = %d", GetLastError()); 00107 return -1; 00108 } 00109 00110 if (realtime) { 00111 00112 jack_log("Create RT thread"); 00113 if (!SetThreadPriority(*thread, THREAD_PRIORITY_TIME_CRITICAL)) { 00114 jack_error("Cannot set priority class = %d", GetLastError()); 00115 return -1; 00116 } 00117 00118 } else { 00119 jack_log("Create non RT thread"); 00120 } 00121 00122 return 0; 00123 } 00124 00125 // voir http://www.microsoft.com/belux/msdn/nl/community/columns/ldoc/multithread1.mspx 00126 00127 int JackWinThread::Kill() 00128 { 00129 if (fThread != (HANDLE)NULL) { // If thread has been started 00130 TerminateThread(fThread, 0); 00131 WaitForSingleObject(fThread, INFINITE); 00132 CloseHandle(fThread); 00133 jack_log("JackWinThread::Kill"); 00134 fThread = (HANDLE)NULL; 00135 fStatus = kIdle; 00136 return 0; 00137 } else { 00138 return -1; 00139 } 00140 } 00141 00142 int JackWinThread::Stop() 00143 { 00144 if (fThread != (HANDLE)NULL) { // If thread has been started 00145 jack_log("JackWinThread::Stop"); 00146 fStatus = kIdle; // Request for the thread to stop 00147 WaitForSingleObject(fEvent, INFINITE); 00148 CloseHandle(fThread); 00149 fThread = (HANDLE)NULL; 00150 return 0; 00151 } else { 00152 return -1; 00153 } 00154 } 00155 00156 int JackWinThread::KillImp(jack_native_thread_t thread) 00157 { 00158 if (thread != (HANDLE)NULL) { // If thread has been started 00159 TerminateThread(thread, 0); 00160 WaitForSingleObject(thread, INFINITE); 00161 CloseHandle(thread); 00162 return 0; 00163 } else { 00164 return -1; 00165 } 00166 } 00167 00168 int JackWinThread::StopImp(jack_native_thread_t thread) 00169 { 00170 if (thread) { // If thread has been started 00171 WaitForSingleObject(thread, INFINITE); 00172 CloseHandle(thread); 00173 return 0; 00174 } else { 00175 return -1; 00176 } 00177 } 00178 00179 int JackWinThread::AcquireRealTime() 00180 { 00181 return (fThread != (HANDLE)NULL) ? AcquireRealTimeImp(fThread, fPriority) : -1; 00182 } 00183 00184 int JackWinThread::AcquireSelfRealTime() 00185 { 00186 return AcquireRealTimeImp(GetCurrentThread(), fPriority); 00187 } 00188 00189 int JackWinThread::AcquireRealTime(int priority) 00190 { 00191 fPriority = priority; 00192 return AcquireRealTime(); 00193 } 00194 00195 int JackWinThread::AcquireSelfRealTime(int priority) 00196 { 00197 fPriority = priority; 00198 return AcquireSelfRealTime(); 00199 } 00200 00201 int JackWinThread::AcquireRealTimeImp(jack_native_thread_t thread, int priority) 00202 { 00203 jack_log("JackWinThread::AcquireRealTimeImp priority = %d", priority); 00204 00205 if (priority >= 90 && MMCSSAcquireRealTime(thread) == 0) { 00206 jack_info("MMCSS API used to acquire RT for thread"); 00207 return 0; 00208 } else { 00209 jack_info("MMCSS API not used..."); 00210 if (SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL)) { 00211 return 0; 00212 } else { 00213 jack_error("Cannot set thread priority = %d", GetLastError()); 00214 return -1; 00215 } 00216 } 00217 } 00218 00219 int JackWinThread::DropRealTime() 00220 { 00221 return (fThread != (HANDLE)NULL) ? DropRealTimeImp(fThread) : -1; 00222 } 00223 00224 int JackWinThread::DropSelfRealTime() 00225 { 00226 return DropRealTimeImp(GetCurrentThread()); 00227 } 00228 00229 int JackWinThread::DropRealTimeImp(jack_native_thread_t thread) 00230 { 00231 if (MMCSSDropRealTime(thread) == 0 ) { 00232 jack_info("MMCSS API used to drop RT for thread"); 00233 return 0; 00234 } else if (SetThreadPriority(thread, THREAD_PRIORITY_NORMAL)) { 00235 return 0; 00236 } else { 00237 jack_error("Cannot set thread priority = %d", GetLastError()); 00238 return -1; 00239 } 00240 } 00241 00242 jack_native_thread_t JackWinThread::GetThreadID() 00243 { 00244 return fThread; 00245 } 00246 00247 bool JackWinThread::IsThread() 00248 { 00249 return GetCurrentThread() == fThread; 00250 } 00251 00252 void JackWinThread::Terminate() 00253 { 00254 jack_log("JackWinThread::Terminate"); 00255 ExitThread(0); 00256 } 00257 00258 SERVER_EXPORT void ThreadExit() 00259 { 00260 jack_log("ThreadExit"); 00261 ExitThread(0); 00262 } 00263 00264 } // end of namespace 00265 00266 bool jack_get_thread_realtime_priority_range(int * min_ptr, int * max_ptr) 00267 { 00268 return false; 00269 } 00270 00271 bool jack_tls_allocate_key(jack_tls_key *key_ptr) 00272 { 00273 DWORD key; 00274 00275 key = TlsAlloc(); 00276 if (key == TLS_OUT_OF_INDEXES) 00277 { 00278 jack_error("TlsAlloc() failed. Error is %d", (unsigned int)GetLastError()); 00279 return false; 00280 } 00281 00282 *key_ptr = key; 00283 return true; 00284 } 00285 00286 bool jack_tls_free_key(jack_tls_key key) 00287 { 00288 if (!TlsFree(key)) 00289 { 00290 jack_error("TlsFree() failed. Error is %d", (unsigned int)GetLastError()); 00291 return false; 00292 } 00293 00294 return true; 00295 } 00296 00297 bool jack_tls_set(jack_tls_key key, void *data_ptr) 00298 { 00299 if (!TlsSetValue(key, data_ptr)) 00300 { 00301 jack_error("TlsSetValue() failed. Error is %d", (unsigned int)GetLastError()); 00302 return false; 00303 } 00304 00305 return true; 00306 } 00307 00308 void *jack_tls_get(jack_tls_key key) 00309 { 00310 return TlsGetValue(key); 00311 }