00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <spl/threading/Thread.h>
00019 #ifdef HAVE_UNISTD_H
00020 #include <unistd.h>
00021 #endif
00022 #ifdef HAVE_STRING_H
00023 #include <string.h>
00024 #endif
00025
00026 #include <spl/Exception.h>
00027 #include <spl/Log.h>
00028
00029 #ifndef _WINDOWS
00030 void *TheThread(void *param);
00031 #endif
00032
00033 Thread::Thread()
00034 : m_joinmutex(), m_hasrun(false)
00035 {
00036 DEBUG_ENABLE_HEAP_LOCK();
00037 m_running = false;
00038 }
00039
00040 #ifdef _WINDOWS
00041 Thread::Thread(HANDLE threadhandle)
00042 : m_joinmutex(), m_hasrun(false)
00043 {
00044 m_running = false;
00045 m_threadhandle = threadhandle;
00046 m_threadid = 0;
00047 }
00048 #endif
00049
00050 #ifndef _WINDOWS
00051 Thread::Thread(pthread_t thread)
00052 : m_joinmutex(), m_hasrun(false)
00053 {
00054 DEBUG_ENABLE_HEAP_LOCK();
00055 m_running = false;
00056 m_threadid = thread;
00057 }
00058 #endif
00059
00060 Thread::~Thread()
00061 {
00062 if ( m_running )
00063 {
00064 Kill();
00065 m_running = false;
00066 }
00067 #ifdef _WIN32
00068 if ( NULL != m_threadhandle && m_running )
00069 {
00070 CloseHandle(m_threadhandle);
00071 m_threadhandle = NULL;
00072 m_running = false;
00073 }
00074 #else
00075
00076 #endif
00077 }
00078
00079 void Thread::Start()
00080 {
00081 if (m_running)
00082 {
00083 throw new Exception("Thread has already started");
00084 }
00085
00086 #ifdef _WIN32
00087 m_threadhandle = CreateThread(NULL,0,TheThread,this,0,&m_threadid);
00088 if (m_threadhandle == NULL)
00089 {
00090 throw new ThreadStartException();
00091 }
00092 #else
00093 int ret = pthread_create(&m_threadid, NULL, TheThread, this);
00094 if (0 != ret )
00095 {
00096 throw new ThreadStartException();
00097 }
00098 #endif
00099
00100
00101 while (!m_running && !m_hasrun)
00102 {
00103 Thread::YYield();
00104 }
00105 }
00106
00107 void Thread::Kill()
00108 {
00109 Thread::YYield();
00110 if (!m_running)
00111 {
00112 return;
00113 }
00114 m_running = false;
00115 m_hasrun = true;
00116 #ifdef _WIN32
00117 TerminateThread( m_threadhandle, 0 );
00118 m_threadhandle = NULL;
00119 #else
00120 pthread_cancel( m_threadid );
00121 memset(&m_threadid, 0, sizeof(pthread_t));
00122 #endif
00123 }
00124
00125 bool Thread::IsRunning() const
00126 {
00127 return m_running;
00128 }
00129
00130 void Thread::Join()
00131 {
00132 m_joinmutex.SetTimeout( 0 );
00133 m_joinmutex.Lock();
00134 m_joinmutex.Unlock();
00135 }
00136
00137 bool Thread::Join( int timeoutMs )
00138 {
00139 m_joinmutex.SetTimeout( timeoutMs );
00140 if ( ! m_joinmutex.Lock() )
00141 {
00142 return false;
00143 }
00144 m_joinmutex.Unlock();
00145 return true;
00146 }
00147
00148 void Thread::SetPriority( enum ThreadPriority prilv )
00149 {
00150 #ifdef WIN32
00151 if ( Thread::PRIORITY_NORMAL == prilv )
00152 {
00153 SetThreadPriority(m_threadhandle, THREAD_PRIORITY_NORMAL);
00154 }
00155 else if ( Thread::PRIORITY_HI == prilv )
00156 {
00157 SetThreadPriority(m_threadhandle, THREAD_PRIORITY_ABOVE_NORMAL);
00158 }
00159 else
00160 {
00161 SetThreadPriority(m_threadhandle, THREAD_PRIORITY_BELOW_NORMAL);
00162 }
00163 #else
00164 struct sched_param sc;
00165 if ( Thread::PRIORITY_NORMAL == prilv )
00166 {
00167
00168 sc.sched_priority = (sched_get_priority_max(SCHED_FIFO) -
00169 sched_get_priority_min(SCHED_FIFO))/2;
00170 pthread_setschedparam(m_threadid, SCHED_FIFO, &sc);
00171 }
00172 else if ( Thread::PRIORITY_HI == prilv )
00173 {
00174 sc.sched_priority = sched_get_priority_max(SCHED_FIFO);
00175 pthread_setschedparam(m_threadid, SCHED_FIFO, &sc);
00176 }
00177 else
00178 {
00179 sc.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
00180 pthread_setschedparam(m_threadid, SCHED_FIFO, &sc);
00181 }
00182 #endif
00183 }
00184
00185 #ifdef _WINDOWS
00186 DWORD WINAPI Thread::TheThread(void *param)
00187 {
00188 Thread *thread = (Thread *)param;
00189
00190 thread->m_joinmutex.Lock();
00191 thread->m_running = true;
00192
00193 try
00194 {
00195 thread->Run();
00196 }
00197 catch (Exception *ex)
00198 {
00199 Log::SWrite(ex);
00200 delete ex;
00201 }
00202 catch (OutOfMemoryException mex)
00203 {
00204 Log::SWrite(mex);
00205 }
00206
00207 thread->m_hasrun = true;
00208 thread->m_running = false;
00209 thread->m_joinmutex.Unlock();
00210
00211 return 0;
00212 }
00213 #else
00214 void *TheThread(void *param)
00215 {
00216 Thread *thread = (Thread *)param;
00217
00218 thread->m_joinmutex.Lock();
00219 thread->m_running = true;
00220
00221 try
00222 {
00223 thread->Run();
00224 }
00225 catch (Exception *ex)
00226 {
00227 Log::SWrite(ex);
00228 delete ex;
00229 }
00230 catch (OutOfMemoryException mex)
00231 {
00232 Log::SWrite(mex);
00233 }
00234
00235 thread->m_hasrun = true;
00236 thread->m_running = false;
00237 thread->m_joinmutex.Unlock();
00238
00239 return NULL;
00240 }
00241 #endif
00242
00243 void Thread::YYield()
00244 {
00245 #ifdef _WIN32
00246 ::Sleep( 1 );
00247 #else
00248 sched_yield();
00249 #endif
00250 }
00251
00252 void Thread::Sleep( long ms )
00253 {
00254 #ifdef _WIN32
00255 ::Sleep( ms );
00256 #else
00257 sleep( (unsigned int)(ms/1000.0) );
00258 #endif
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 #if defined(DEBUG)
00273 void Thread::CheckMem() const
00274 {
00275 }
00276
00277 void Thread::ValidateMem() const
00278 {
00279 }
00280 #endif