Jack2 1.9.7
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(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::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(jack_native_thread_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 jack_native_thread_t JackWinThread::GetThreadID()
00234 {
00235     return fThread;
00236 }
00237 
00238 bool JackWinThread::IsThread()
00239 {
00240     return GetCurrentThread() == fThread;
00241 }
00242 
00243 void JackWinThread::Terminate()
00244 {
00245     jack_log("JackWinThread::Terminate");
00246     ExitThread(0);
00247 }
00248 
00249 SERVER_EXPORT void ThreadExit()
00250 {
00251     jack_log("ThreadExit");
00252     ExitThread(0);
00253 }
00254 
00255 } // end of namespace
00256 
00257 bool jack_get_thread_realtime_priority_range(int * min_ptr, int * max_ptr)
00258 {
00259     return false;
00260 }
00261 
00262 bool jack_tls_allocate_key(jack_tls_key *key_ptr)
00263 {
00264     DWORD key;
00265 
00266     key = TlsAlloc();
00267     if (key == TLS_OUT_OF_INDEXES)
00268     {
00269         jack_error("TlsAlloc() failed. Error is %d", (unsigned int)GetLastError());
00270         return false;
00271     }
00272 
00273     *key_ptr = key;
00274     return true;
00275 }
00276 
00277 bool jack_tls_free_key(jack_tls_key key)
00278 {
00279     if (!TlsFree(key))
00280     {
00281         jack_error("TlsFree() failed. Error is %d", (unsigned int)GetLastError());
00282         return false;
00283     }
00284 
00285     return true;
00286 }
00287 
00288 bool jack_tls_set(jack_tls_key key, void *data_ptr)
00289 {
00290     if (!TlsSetValue(key, data_ptr))
00291     {
00292         jack_error("TlsSetValue() failed. Error is %d", (unsigned int)GetLastError());
00293         return false;
00294     }
00295 
00296     return true;
00297 }
00298 
00299 void *jack_tls_get(jack_tls_key key)
00300 {
00301     return TlsGetValue(key);
00302 }

Generated for Jack2 by doxygen 1.7.4