JackWinThread.cpp

00001 /*
00002 Copyright (C) 2001 Paul Davis 
00003 Copyright (C) 2004-2006 Grame
00004 
00005 This program is free software; you can redistribute it and/or modify
00006 it under the terms of the GNU General Public License as published by
00007 the Free Software Foundation; either version 2 of the License, or
00008 (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 
00019 */
00020 
00021 #include "JackWinThread.h"
00022 #include "JackError.h"
00023 #include <assert.h>
00024 
00025 namespace Jack
00026 {
00027 
00028 DWORD WINAPI JackWinThread::ThreadHandler(void* arg)
00029 {
00030     JackWinThread* obj = (JackWinThread*)arg;
00031     JackRunnableInterface* runnable = obj->fRunnable;
00032 
00033     // Call Init method
00034     if (!runnable->Init()) {
00035         jack_error("Thread init fails: thread quits");
00036         return 0;
00037     }
00038 
00039     // Signal creation thread when started with StartSync
00040     if (!obj->fRunning) {
00041         obj->fRunning = true;
00042         SetEvent(obj->fEvent);
00043     }
00044 
00045     JackLog("ThreadHandler: start\n");
00046 
00047     // If Init succeed, start the thread loop
00048     bool res = true;
00049     while (obj->fRunning && res) {
00050         res = runnable->Execute();
00051     }
00052   
00053     SetEvent(obj->fEvent);
00054     JackLog("ThreadHandler: exit\n");
00055     return 0;
00056 }
00057 
00058 JackWinThread::JackWinThread(JackRunnableInterface* runnable) 
00059         : JackThread(runnable, 0, false, 0)
00060 {
00061          fEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
00062          fThread = NULL;
00063          assert(fEvent);
00064 }
00065 
00066 JackWinThread::~JackWinThread()
00067 {
00068         CloseHandle(fEvent);
00069 }
00070 
00071 int JackWinThread::Start()
00072 {
00073         fEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
00074     if (fEvent == NULL) {
00075         jack_error("Cannot create event error = %d", GetLastError());
00076         return -1;
00077     }
00078 
00079         fRunning = true;
00080         
00081         // Check if the thread was correctly started
00082         if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { 
00083                 fRunning = false;
00084                 return -1;
00085         } else {
00086                 return 0;
00087         }
00088 }
00089 
00090 int JackWinThread::StartImp(pthread_t* thread, int priority, int realtime, ThreadCallback start_routine, void* arg)
00091 {
00092     DWORD id;
00093 
00094     if (realtime) {
00095 
00096         JackLog("Create RT thread\n");
00097         *thread = CreateThread(NULL, 0, start_routine, arg, 0, &id);
00098 
00099         if (*thread == NULL) {
00100             jack_error("Cannot create thread error = %d", GetLastError());
00101             return -1;
00102         }
00103 
00104         if (!SetThreadPriority(*thread, THREAD_PRIORITY_TIME_CRITICAL)) {
00105             jack_error("Cannot set priority class = %d", GetLastError());
00106             return -1;
00107         }
00108 
00109         return 0;
00110 
00111     } else {
00112 
00113         JackLog("Create non RT thread\n");
00114         *thread = CreateThread(NULL, 0, start_routine, arg, 0, &id);
00115 
00116         if (thread == NULL) {
00117             jack_error("Cannot create thread error = %d", GetLastError());
00118             return -1;
00119         }
00120 
00121         return 0;
00122     }
00123 }
00124 
00125 int JackWinThread::StartSync()
00126 {
00127     DWORD id;
00128 
00129     fEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
00130     if (fEvent == NULL) {
00131         jack_error("Cannot create event error = %d", GetLastError());
00132         return -1;
00133     }
00134 
00135     if (fRealTime) {
00136 
00137         JackLog("Create RT thread\n");
00138         fThread = CreateThread(NULL, 0, ThreadHandler, (void*)this, 0, &id);
00139 
00140         if (fThread == NULL) {
00141             jack_error("Cannot create thread error = %d", GetLastError());
00142             return -1;
00143         }
00144 
00145         if (WaitForSingleObject(fEvent, 3000) != WAIT_OBJECT_0) { // wait 3 sec
00146             jack_error("Thread has not started");
00147             return -1;
00148         }
00149 
00150         if (!SetThreadPriority(fThread, THREAD_PRIORITY_TIME_CRITICAL)) {
00151             jack_error("Cannot set priority class = %d", GetLastError());
00152             return -1;
00153         }
00154 
00155         return 0;
00156 
00157     } else {
00158 
00159         JackLog("Create non RT thread\n");
00160         fThread = CreateThread(NULL, 0, ThreadHandler, (void*)this, 0, &id);
00161 
00162         if (fThread == NULL) {
00163             jack_error("Cannot create thread error = %d", GetLastError());
00164             return -1;
00165         }
00166 
00167         if (WaitForSingleObject(fEvent, 3000) != WAIT_OBJECT_0) { // wait 3 sec
00168             jack_error("Thread has not started");
00169             return -1;
00170         }
00171 
00172         return 0;
00173     }
00174 }
00175 
00176 // voir http://www.microsoft.com/belux/msdn/nl/community/columns/ldoc/multithread1.mspx
00177 
00178 int JackWinThread::Kill()
00179 {
00180     if (fThread) { // If thread has been started
00181         TerminateThread(fThread, 0);
00182                 WaitForSingleObject(fThread, INFINITE);
00183         CloseHandle(fThread);
00184                 JackLog("JackWinThread::Kill 2\n");
00185                 fThread = NULL;
00186                 fRunning = false; 
00187         return 0;
00188     } else {
00189         return -1;
00190     }
00191 }
00192 
00193 int JackWinThread::Stop()
00194 {
00195     if (fThread) { // If thread has been started
00196         JackLog("JackWinThread::Stop\n");
00197         fRunning = false; // Request for the thread to stop
00198         WaitForSingleObject(fEvent, INFINITE);
00199         CloseHandle(fThread);
00200                 fThread = NULL;
00201         return 0;
00202     } else {
00203         return -1;
00204     }
00205 }
00206 
00207 int JackWinThread::AcquireRealTime()
00208 {
00209         return (fThread) ? AcquireRealTimeImp(fThread, fPriority) : -1;
00210 }
00211 
00212 int JackWinThread::AcquireRealTime(int priority)
00213 {
00214         fPriority = priority;
00215         return AcquireRealTime();
00216 }
00217 
00218 int JackWinThread::AcquireRealTimeImp(pthread_t thread, int priority)
00219 {
00220     JackLog("JackWinThread::AcquireRealTime\n");
00221 
00222         if (SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL)) {
00223                 JackLog("JackWinThread::AcquireRealTime OK\n");
00224                 return 0;
00225         } else {
00226                 jack_error("Cannot set thread priority = %d", GetLastError());
00227                 return -1;
00228         }
00229 }
00230 int JackWinThread::DropRealTime()
00231 {
00232         return DropRealTimeImp(fThread);
00233 }
00234 
00235 int JackWinThread::DropRealTimeImp(pthread_t thread)
00236 {
00237         if (SetThreadPriority(thread, THREAD_PRIORITY_NORMAL)) {
00238                 return 0;
00239         } else {
00240                 jack_error("Cannot set thread priority = %d", GetLastError());
00241                 return -1;
00242         }
00243 }
00244 
00245 pthread_t JackWinThread::GetThreadID()
00246 {
00247     return fThread;
00248 }
00249 
00250 void JackWinThread::Terminate()
00251 {
00252         TerminateThread(fThread, 0);
00253         WaitForSingleObject(fThread, INFINITE);
00254         CloseHandle(fThread);
00255 }
00256 
00257 } // end of namespace
00258 

Generated on Thu Feb 14 11:16:02 2008 for Jackdmp by  doxygen 1.5.1