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
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "cxutils/thread.h"
00041
00042 #include <stdio.h>
00043 #include <string.h>
00044
00045 #ifdef WIN32
00046 #include <windows.h>
00047 #endif
00048
00049 using namespace CxUtils;
00050
00051 unsigned int Thread::Manager::mManagerCount = 0;
00052
00053
00059 Thread::Manager::Manager()
00060 {
00061 mManagerCount++;
00062 }
00063
00064
00070 Thread::Manager::~Manager()
00071 {
00072 StopAllThreads();
00073 }
00074
00075
00088 bool Thread::Manager::CreateThread(const std::string& name, void (*func)(void *), void* args, const int priority)
00089 {
00090 Mutex::ScopedLock lock(&mMutex);
00091 if(mThreads.find(name) == mThreads.end())
00092 {
00093 mThreads[name] = new Thread();
00094 mThreads[name]->CreateThread(func, args);
00095 mThreads[name]->SetThreadName(name);
00096 mThreads[name]->SetThreadPriority(priority);
00097 return true;
00098 }
00099
00100 return false;
00101 }
00102
00103
00112 void Thread::Manager::StopThread(const std::string& name, const int ms)
00113 {
00114 Mutex::ScopedLock lock(&mMutex);
00115 std::map<std::string, Thread*>::iterator t;
00116 t = mThreads.find(name);
00117 if(t != mThreads.end())
00118 {
00119 t->second->StopThread(ms);
00120 delete t->second;
00121 }
00122 }
00123
00124
00130 void Thread::Manager::StopAllThreads()
00131 {
00132 Mutex::ScopedLock lock(&mMutex);
00133 std::map<std::string, Thread*>::iterator t;
00134 for(t = mThreads.begin(); t != mThreads.end(); t++)
00135 {
00136 t->second->StopThread();
00137 delete t->second;
00138 }
00139 mThreads.clear();
00140 }
00141
00142
00152 bool Thread::Manager::IsThreadActive(const std::string& name) const
00153 {
00154 Mutex::ScopedLock lock(&mMutex);
00155 std::map<std::string, Thread*>::const_iterator t;
00156 t = mThreads.find(name);
00157 if(t != mThreads.end())
00158 {
00159 return t->second->IsThreadActive();
00160 }
00161 return false;
00162 }
00163
00164
00175 bool Thread::Manager::QuitThreadFlag(const std::string& name) const
00176 {
00177 Mutex::ScopedLock lock(&mMutex);
00178 std::map<std::string, Thread*>::const_iterator t;
00179 t = mThreads.find(name);
00180 if(t != mThreads.end())
00181 {
00182 return t->second->QuitThreadFlag();
00183 }
00184 return true;
00185 }
00186
00187 #ifdef WIN32
00188 #include <time.h>
00189 #include <windows.h>
00190 unsigned int Thread::mThreadNum = 0;
00191
00192
00193
00194 typedef struct TagTHREADNAME_INFO
00195 {
00196 DWORD dwType;
00197 LPCSTR szName;
00198 DWORD dwThreadID;
00199 DWORD dwFlags;
00200 } THREADNAME_INFO;
00201
00210 void CxSetThreadName(DWORD dwThreadID, LPCSTR szThreadName)
00211 {
00212 #ifndef MINGW
00213 THREADNAME_INFO info;
00214 info.dwType = 0x1000;
00215 info.szName = szThreadName;
00216 info.dwThreadID = dwThreadID;
00217 info.dwFlags = 0;
00218
00219 __try
00220 {
00221 RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info);
00222 }
00223 __except(EXCEPTION_CONTINUE_EXECUTION)
00224 {
00225 }
00226 #endif
00227 }
00228
00239 unsigned long __stdcall Thread::CxThreadProc(void* arg)
00240 {
00241 Thread *pThread = (Thread*)arg;
00242 pThread->mActive = true;
00243
00244 if (pThread->mThreadName.empty() == false)
00245 ::CxSetThreadName(GetCurrentThreadId(), pThread->mThreadName.c_str());
00246
00247 pThread->mFuncCbMutex.Lock();
00248 pThread->Execute();
00249 pThread->mFuncCbMutex.Unlock();
00250 pThread->mActive = false;
00251 return 0;
00252 }
00253
00254 #else
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 void *Thread::CxThreadProc(void *arg)
00266 {
00267
00268 Thread *pThread = (Thread*)arg;
00269 pThread->mActive = true;
00270 pThread->mFuncCbMutex.Lock();
00271 pThread->Execute();
00272
00273 pThread->mFuncCbMutex.Unlock();
00274 pThread->mActive = false;
00275 pthread_exit(NULL);
00276 return 0;
00277 }
00278 #endif
00279
00280
00286 Thread::Thread() : mThreadFunc(0)
00287 {
00288 InitializeThread();
00289 #ifdef WIN32
00290 SetThreadName("CX_Thread");
00291 #endif
00292
00293 }
00294
00302 Thread::Thread(const std::string& name)
00303 {
00304 InitializeThread();
00305 this->SetThreadName(name);
00306 }
00307
00313 std::string Thread::GetThreadName() const { return mThreadName; }
00314
00322 void Thread::SetThreadName(const std::string& name)
00323 {
00324 mThreadName = name;
00325 #ifdef WIN32
00326 if (IsThreadActive())
00327 {
00328 ::CxSetThreadName(mThreadId, mThreadName.c_str());
00329 }
00330 #endif
00331 }
00332
00333
00341 Thread::ID Thread::GetCurrentThreadID()
00342 {
00343 #ifdef WIN32
00344 return GetCurrentThreadId();
00345 #else
00346 return pthread_self();
00347 #endif
00348 }
00349
00350
00356 void Thread::InitializeThread()
00357 {
00358 mActive = false;
00359 mQuitThreadFlag = true;
00360 mThreadId = 0;
00361 mThreadArgs = NULL;
00362 mThreadName = "CX_THREAD";
00363 #ifdef WIN32
00364 mThread = 0;
00365 #endif
00366 }
00367
00368
00374 Thread::~Thread()
00375 {
00376 this->StopThread();
00377 KillThread();
00378 #ifdef WIN32
00379 if(mThread)
00380 {
00381 CloseHandle(mThread);
00382 mThread = NULL;
00383 }
00384 #else
00385
00386 #endif
00387 mThreadName = "CX_THREAD";
00388 }
00389
00390
00391
00400 int Thread::CreateThread()
00401 {
00402
00403 KillThread();
00404 #ifdef WIN32
00405 mThread = ::CreateThread(NULL,
00406 0,
00407 (LPTHREAD_START_ROUTINE)Thread::CxThreadProc,
00408 (LPVOID) this,
00409 0,
00410 (LPDWORD)&mThreadId);
00411
00412 if(mThread == NULL)
00413 return 0;
00414
00415 mActive = true;
00416 mQuitThreadFlag = false;
00417
00418 Sleep(10);
00419
00420 return 1;
00421 #else
00422 int rc;
00423 rc = pthread_create(&mThreadId, NULL, Thread::CxThreadProc, (void *)this);
00424
00425 if(rc)
00426 {
00427 printf("ERROR:Failed to create thread, error code %d\n", rc);
00428 printf("Thread::CreateThread()\n");
00429 return 0;
00430 }
00431 else
00432 {
00433 mActive = true;
00434 mQuitThreadFlag = false;
00435 usleep(10000);
00436 return 1;
00437 }
00438 #endif
00439 }
00440
00441
00455 int Thread::CreateThread(void (*func)(void *), void *args)
00456 {
00457 if(!func)
00458 return false;
00459
00460 StopThread();
00461 mFuncCbMutex.Lock();
00462 this->mThreadFunc = func;
00463 this->mThreadArgs = args;
00464 mFuncCbMutex.Unlock();
00465 return this->CreateThread();
00466 }
00467
00479 int Thread::StopThread(const int ms)
00480 {
00481
00482 int result = 0;
00483
00484 if(!IsThreadActive())
00485 return result;
00486
00487 mQuitThreadFlag = true;
00488
00489 if(mThreadId == Thread::GetCurrentThreadID())
00490 {
00491 return false;
00492 }
00493
00494 for(int i = 0; i < ms; i++)
00495 {
00496 if(!IsThreadActive())
00497 {
00498 result = 1;
00499 break;
00500 }
00501 #ifdef WIN32
00502 Sleep(1);
00503 #else
00504 usleep(1000);
00505 #endif
00506 }
00507
00508 if(IsThreadActive())
00509 return KillThread();
00510
00511 mFuncCbMutex.Lock();
00512 #ifndef WIN32
00513
00514 pthread_join(mThreadId, NULL);
00515 #else
00516 mThread = 0;
00517 #endif
00518 mThreadId = 0;
00519 mThreadFunc = NULL;
00520 mThreadArgs = NULL;
00521 mFuncCbMutex.Unlock();
00522 mThreadName = "CX_THREAD";
00523
00524 return result;
00525 }
00526
00527
00533 bool Thread::IsThreadActive() const
00534 {
00535 return mActive;
00536 }
00537
00538
00546 int Thread::KillThread()
00547 {
00548 mQuitThreadFlag = false;
00549 #ifdef WIN32
00550 int i;
00551 int x;
00552 if(mActive)
00553 {
00554 i = TerminateThread(mThread, 1);
00555 if(i == 0)
00556 x = 0;
00557 else
00558 {
00559 CloseHandle(mThread);
00560 mThread = NULL;
00561 mActive = false;
00562 x = 1;
00563 }
00564 }
00565 else
00566 {
00567 if(mThread != NULL)
00568 {
00569 CloseHandle(mThread);
00570 mThread = NULL;
00571 }
00572 x = 1;
00573 }
00574
00575 return x;
00576 #else
00577 if(mActive)
00578 {
00579 if(pthread_kill(mThreadId, 1))
00580 {
00581 return 0;
00582 }
00583 else
00584 {
00585 mThreadId = 0;
00586 mActive = false;
00587 return 1;
00588 }
00589 }
00590 else
00591 {
00592 mThreadId = 0;
00593 return 1;
00594 }
00595 #endif
00596 }
00597
00598
00599
00605 Thread::ID Thread::GetThreadID() const
00606 {
00607 return mThreadId;
00608 }
00609
00610
00620 int Thread::SetThreadPriority(const int priority)
00621 {
00622 #if WIN32
00623 if (IsThreadActive())
00624 {
00625 int winPriority = 0;
00626 if(priority > 0 && priority <= 16)
00627 {
00628 winPriority = THREAD_PRIORITY_ABOVE_NORMAL;
00629 }
00630 else if(priority > 16 && priority < 33)
00631 {
00632 winPriority = THREAD_PRIORITY_HIGHEST;
00633 }
00634 else if(priority >= 33)
00635 {
00636 winPriority = THREAD_PRIORITY_TIME_CRITICAL;
00637 }
00638 else if(priority < 0 && priority >= -16)
00639 {
00640 winPriority = THREAD_PRIORITY_BELOW_NORMAL;
00641 }
00642 else if(priority < -16 && priority > -33)
00643 {
00644 winPriority = THREAD_PRIORITY_LOWEST;
00645 }
00646 else if(priority <= -33)
00647 {
00648 winPriority = THREAD_PRIORITY_IDLE;
00649 }
00650 if(::SetThreadPriority(mThread, winPriority))
00651 return 1;
00652 else
00653 return 0;
00654 }
00655 #else
00656 if(IsThreadActive())
00657 {
00658 int ret = 0;
00659 int linPriority = abs((int)(priority + 49.0)/100.0);
00660 if(linPriority > 99)
00661 linPriority = 99;
00662 struct sched_param param;
00663 param.sched_priority = linPriority;
00664
00665 ret = pthread_setschedparam(mThreadId, SCHED_OTHER, ¶m);
00666 if(ret == 0)
00667 return 1;
00668 }
00669 #endif
00670 return 0;
00671 }
00672
00673
00679 bool Thread::QuitThreadFlag() const { return mQuitThreadFlag; }
00680
00681
00691 void Thread::Execute()
00692 {
00693 if(this->mThreadFunc)
00694 mThreadFunc(mThreadArgs);
00695 }
00696
00697