Jack2 1.9.6
|
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 00021 #include "JackWinThread.h" 00022 #include "JackError.h" 00023 #include "JackTime.h" 00024 #include <assert.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 : 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(pthread_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(pthread_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(pthread_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(pthread_t thread, int priority) 00202 { 00203 jack_log("JackWinThread::AcquireRealTime"); 00204 00205 if (SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL)) { 00206 return 0; 00207 } else { 00208 jack_error("Cannot set thread priority = %d", GetLastError()); 00209 return -1; 00210 } 00211 } 00212 00213 int JackWinThread::DropRealTime() 00214 { 00215 return (fThread != (HANDLE)NULL) ? DropRealTimeImp(fThread) : -1; 00216 } 00217 00218 int JackWinThread::DropSelfRealTime() 00219 { 00220 return DropRealTimeImp(GetCurrentThread()); 00221 } 00222 00223 int JackWinThread::DropRealTimeImp(pthread_t thread) 00224 { 00225 if (SetThreadPriority(thread, THREAD_PRIORITY_NORMAL)) { 00226 return 0; 00227 } else { 00228 jack_error("Cannot set thread priority = %d", GetLastError()); 00229 return -1; 00230 } 00231 } 00232 00233 pthread_t JackWinThread::GetThreadID() 00234 { 00235 return fThread; 00236 } 00237 00238 void JackWinThread::Terminate() 00239 { 00240 jack_log("JackWinThread::Terminate"); 00241 ExitThread(0); 00242 } 00243 00244 SERVER_EXPORT void ThreadExit() 00245 { 00246 jack_log("ThreadExit"); 00247 ExitThread(0); 00248 } 00249 00250 } // end of namespace 00251 00252 bool jack_get_thread_realtime_priority_range(int * min_ptr, int * max_ptr) 00253 { 00254 return false; 00255 } 00256 00257 bool jack_tls_allocate_key(jack_tls_key *key_ptr) 00258 { 00259 DWORD key; 00260 00261 key = TlsAlloc(); 00262 if (key == TLS_OUT_OF_INDEXES) 00263 { 00264 jack_error("TlsAlloc() failed. Error is %d", (unsigned int)GetLastError()); 00265 return false; 00266 } 00267 00268 *key_ptr = key; 00269 return true; 00270 } 00271 00272 bool jack_tls_free_key(jack_tls_key key) 00273 { 00274 if (!TlsFree(key)) 00275 { 00276 jack_error("TlsFree() failed. Error is %d", (unsigned int)GetLastError()); 00277 return false; 00278 } 00279 00280 return true; 00281 } 00282 00283 bool jack_tls_set(jack_tls_key key, void *data_ptr) 00284 { 00285 if (!TlsSetValue(key, data_ptr)) 00286 { 00287 jack_error("TlsSetValue() failed. Error is %d", (unsigned int)GetLastError()); 00288 return false; 00289 } 00290 00291 return true; 00292 } 00293 00294 void *jack_tls_get(jack_tls_key key) 00295 { 00296 return TlsGetValue(key); 00297 }