Thread.cxx

Go to the documentation of this file.
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 
Generated by  doxygen 1.6.3