CLAM-Development
1.1
|
00001 /* 00002 * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG) 00003 * UNIVERSITAT POMPEU FABRA 00004 * 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 * 00020 */ 00021 00022 #include "Thread.hxx" 00023 #include "Mutex.hxx" 00024 #include "xtime.hxx" 00025 #include "Assert.hxx" 00026 #include <sched.h> 00027 #ifndef WIN32 00028 #include <cstdio> 00029 #endif 00030 #ifdef WIN32 00031 #include "CLAM_windows.h" 00032 #undef GetClassName 00033 #endif 00034 00035 typedef void *(*pthread_start_pfunc) (void *); 00036 00037 typedef void (*pthread_clean_pfunc) (void *); 00038 00039 namespace CLAM 00040 { 00041 00042 Thread::Thread(bool realtime): 00043 mRealtime(realtime), 00044 mHasCode( false ), 00045 mHasCleanup( false ), 00046 mIsCancelled(false), 00047 mRunning(false) 00048 { 00049 } 00050 00051 Thread::~Thread() 00052 { 00053 if ( mRunning ) 00054 Stop(); 00055 } 00056 00057 void Thread::SetupPriorityPolicy() 00058 { 00059 #ifdef WIN32 00060 BOOL res; 00061 DWORD err; 00062 00063 res = SetPriorityClass(GetCurrentProcess(),NORMAL_PRIORITY_CLASS ); 00064 err = GetLastError(); 00065 res = SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_NORMAL ); 00066 err = GetLastError(); 00067 #else 00068 if (mRealtime) 00069 { 00070 struct sched_param sched_param; 00071 int policy; 00072 00073 if (pthread_getschedparam(pthread_self(), &policy, &sched_param) < 0) { 00074 printf("Scheduler getparam failed...\n"); 00075 } 00076 sched_param.sched_priority = sched_get_priority_max(SCHED_RR)-1; 00077 if (!pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param)) { 00078 printf("Scheduler set to Round Robin with priority %i...\n", sched_param.sched_priority); 00079 } 00080 }else{ 00081 struct sched_param sched_param; 00082 int policy; 00083 00084 if (pthread_getschedparam(pthread_self(), &policy, &sched_param) < 0) { 00085 printf("Scheduler getparam failed...\n"); 00086 } 00087 sched_param.sched_priority = sched_get_priority_max(policy)/2; 00088 pthread_setschedparam(pthread_self(), policy, &sched_param); 00089 } 00090 #endif 00091 } 00092 00093 void Thread::Start() 00094 { 00095 CLAM_ASSERT( mHasCode, "The thread has no code to execute!" ); 00096 00097 mRunning = true; 00098 pthread_create(&mThreadID, NULL, (pthread_start_pfunc)LaunchThread, this ); 00099 } 00100 00101 void Thread::Stop() 00102 { 00103 LaunchThreadCleanup(this); 00104 mIsCancelled = true; 00105 mIsCancelled = false; 00106 mRunning = false; 00107 } 00108 00109 void Thread::Yield() 00110 { 00111 int ret; 00112 ret = sched_yield(); 00113 00114 CLAM_ASSERT( ret == 0, "The thread cannot yield?!!" ); 00115 } 00116 00117 void Thread::SetThreadCode( const CBL::Functor0& thread_code ) 00118 { 00119 mThreadCode = thread_code; 00120 mHasCode = true; 00121 } 00122 00123 void Thread::SetCleanupCode( const CBL::Functor0& cleanup_code ) 00124 { 00125 mCleanUpCode = cleanup_code; 00126 mHasCleanup = true; 00127 } 00128 00129 void* Thread::LaunchThread( void* pvoid ) 00130 { 00131 Thread* pSelf = (Thread*)pvoid; 00132 00133 pSelf->mRunning=true; 00134 pSelf->SetupPriorityPolicy(); 00135 pSelf->mThreadCode(); 00136 pSelf->mRunning = false; 00137 pthread_exit(NULL); 00138 00139 return NULL; 00140 } 00141 00142 void Thread::LaunchThreadCleanup( void* pvoid ) 00143 { 00144 Thread* pSelf = (Thread*)pvoid; 00145 if ( pSelf->mHasCleanup ) 00146 pSelf->mCleanUpCode(); 00147 00148 pthread_join( pSelf->mThreadID, NULL ); 00149 } 00150 00151 void Thread::Sleep( unsigned int milliseconds ) 00152 { 00153 SleepDetail( milliseconds ); 00154 } 00155 00156 void Thread::Sleep() 00157 { 00158 SleepDetail( 31536000 ); // 1 year 00159 } 00160 00161 void Thread::SleepDetail( unsigned int milliseconds) 00162 { 00163 00164 xtime xt; 00165 00166 to_time( milliseconds, xt ); 00167 00168 Mutex aMutex; 00169 00170 Mutex::ScopedLock lock( aMutex ); 00171 00172 mSleepCondition.TimedWait( lock, xt ); 00173 00174 } 00175 00176 void Thread::WakeUp() 00177 { 00178 Mutex localMutex; 00179 00180 Mutex::ScopedLock lock( localMutex ); 00181 00182 mSleepCondition.NotifyOne(); 00183 } 00184 00185 } 00186