Thread.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 );
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