Jack2 1.9.6

JackWinThread.cpp

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 }