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
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 #include <blort/ThreadObject/Thread.h>
00079
00080
00081 #ifndef WINDOWS
00082 extern "C"
00083 {
00084 int usleep(useconds_t useconds);
00085 #ifdef NANO_SECOND_SLEEP
00086 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
00087 #endif
00088 }
00089
00090 void Sleep( unsigned int milli )
00091 {
00092 #ifdef NANO_SECOND_SLEEP
00093 struct timespec interval, remainder;
00094 milli = milli * 1000000;
00095 interval.tv_sec= 0;
00096 interval.tv_nsec=milli;
00097 nanosleep(&interval,&remainder);
00098 #else
00099 usleep(milli*1000);
00100 #endif
00101 }
00102 #endif
00103
00104 #include <iostream>
00105 using namespace std;
00106
00114 #ifdef WINDOWS
00115 DWORD WINAPI
00116 #else
00117 LPVOID
00118 #endif
00119 _THKERNEL( LPVOID lpvData
00120 )
00121 {
00122 CThread *pThread = (CThread *)lpvData;
00123 ThreadType_t lastType;
00124
00125
00126
00127
00128
00129
00130
00131 pThread->m_mutex.Lock();
00132 pThread->m_state = ThreadStateWaiting;
00133 pThread->m_bRunning = TRUE;
00134 #ifndef WINDOWS
00135 pThread->m_dwId = CThread::ThreadId();
00136 #endif
00137 pThread->m_mutex.Unlock();
00138
00139 while( TRUE )
00140 {
00141 lastType = pThread->m_type;
00142
00143 if( lastType == ThreadTypeEventDriven )
00144 {
00145 if( ! pThread->m_event.Wait() )
00146 break;
00147 }
00148
00149 if( ! pThread->KernelProcess() )
00150 break;
00151
00152
00153 if( lastType == ThreadTypeEventDriven )
00154 pThread->m_event.Reset();
00155
00156 if( pThread->m_type == ThreadTypeIntervalDriven )
00157 Sleep(pThread->m_dwIdle);
00158
00159 }
00160
00161
00162 pThread->m_mutex.Lock();
00163 pThread->m_state = ThreadStateDown;
00164 pThread->m_bRunning = FALSE;
00165 pThread->m_mutex.Unlock();
00166
00167
00168 #ifdef WINDOWS
00169 return 0;
00170 #else
00171 return (LPVOID)0;
00172 #endif
00173 }
00174
00182 BOOL
00183 CThread::OnTask( LPVOID lpvData
00184 )
00185 {
00186 CTask *pTask = (CTask *)lpvData;
00187
00188 pTask->SetTaskStatus(TaskStatusBeingProcessed);
00189
00190 BOOL bReturn = pTask->Task();
00191
00192 pTask->SetTaskStatus(TaskStatusCompleted);
00193
00194
00195 return bReturn;
00196 }
00197
00198
00206 BOOL
00207 CThread::OnTask()
00208 {
00209 printf("\nthread is alive\n");
00210
00211 return TRUE;
00212 }
00213
00214
00215 BOOL
00216 CThread::Event(CTask *pvTask
00217 )
00218 {
00219 ThreadId_t id;
00220 m_mutex.Lock();
00221 if( m_type != ThreadTypeEventDriven )
00222 {
00223 m_mutex.Unlock();
00224 m_dwObjectCondition |= ILLEGAL_USE_OF_EVENT;
00225 m_state = ThreadStateFault;
00226 return FALSE;
00227 }
00228
00229 m_mutex.Unlock();
00230 GetId(&id);
00231 pvTask->SetId(&id);
00232 if( ! Push((LPVOID)pvTask) )
00233 return FALSE;
00234
00235 pvTask->SetTaskStatus(TaskStatusWaitingOnQueue);
00236 m_event.Set();
00237
00238 return TRUE;
00239 }
00240
00247 BOOL
00248 CThread::Event(LPVOID lpvData
00249 )
00250 {
00251 m_mutex.Lock();
00252 if( m_type != ThreadTypeEventDriven )
00253 {
00254 m_mutex.Unlock();
00255 m_dwObjectCondition |= ILLEGAL_USE_OF_EVENT;
00256 m_state = ThreadStateFault;
00257 return FALSE;
00258 }
00259
00260 m_mutex.Unlock();
00261 if( ! Push(lpvData) )
00262 return FALSE;
00263
00264 m_event.Set();
00265
00266 return TRUE;
00267 }
00268
00269
00278 void
00279 CThread::SetPriority(DWORD dwPriority)
00280 {
00281
00282 #ifdef WINDOWS
00283 SetThreadPriority(m_thread,dwPriority);
00284 #endif
00285 }
00286
00287
00294 BOOL
00295 CThread::KernelProcess()
00296 {
00297
00298 m_mutex.Lock();
00299 m_state = ThreadStateBusy;
00300 if( !m_bRunning )
00301 {
00302 m_state = ThreadStateShuttingDown;
00303 m_mutex.Unlock();
00304 return FALSE;
00305 }
00306 m_mutex.Unlock();
00307
00308 if( !Empty() )
00309 {
00310 while( !Empty() )
00311 {
00312 Pop();
00313 if( !OnTask(m_lpvProcessor) )
00314 {
00315 m_mutex.Lock();
00316 m_lpvProcessor = NULL;
00317 m_state = ThreadStateShuttingDown;
00318 m_mutex.Unlock();
00319 return FALSE;
00320 }
00321 }
00322 m_mutex.Lock();
00323 m_lpvProcessor = NULL;
00324 m_state = ThreadStateWaiting;
00325 }
00326 else {
00327 if( !OnTask() )
00328 {
00329 m_mutex.Lock();
00330 m_state = ThreadStateShuttingDown;
00331 m_mutex.Unlock();
00332 return FALSE;
00333 }
00334 m_mutex.Lock();
00335 m_state = ThreadStateWaiting;
00336 }
00337
00338 m_mutex.Unlock();
00339
00340 return TRUE;
00341 }
00342
00343
00351 unsigned int
00352 CThread::GetEventsPending()
00353 {
00354 unsigned int chEventsWaiting;
00355
00356 m_mutex.Lock();
00357 chEventsWaiting = m_quePos;
00358 m_mutex.Unlock();
00359
00360 return chEventsWaiting;
00361 }
00362
00363
00371 CThread::CThread(void)
00372 :m_bRunning(FALSE)
00373 #ifdef WINDOWS
00374 ,m_thread(NULL)
00375 #endif
00376 ,m_dwId(0L)
00377 ,m_chQue(QUE_SIZE)
00378 ,m_quePos(0)
00379 ,m_lpvProcessor(NULL)
00380 ,m_dwIdle(100)
00381 ,m_type(ThreadTypeEventDriven)
00382 ,m_stackSize(DEFAULT_STACK_SIZE)
00383 {
00384
00385 m_dwObjectCondition = NO_ERRORS;
00386
00387 m_lppvQue = new LPVOID [QUE_SIZE];
00388
00389 if( !m_lppvQue )
00390 {
00391 m_dwObjectCondition |= MEMORY_FAULT;
00392 m_state = ThreadStateFault;
00393 return;
00394 }
00395
00396 if( !m_mutex.m_bCreated )
00397 {
00398 perror("mutex creation failed");
00399 m_dwObjectCondition |= MUTEX_CREATION;
00400 m_state = ThreadStateFault;
00401 return;
00402 }
00403
00404
00405 if( !m_event.m_bCreated )
00406 {
00407 perror("event creation failed");
00408 m_dwObjectCondition |= EVENT_CREATION;
00409 m_state = ThreadStateFault;
00410 return;
00411 }
00412
00413
00414 Start();
00415
00416 }
00417
00425 BOOL
00426 CThread::Empty()
00427 {
00428 m_mutex.Lock();
00429 if( m_quePos <= 0 )
00430 {
00431 m_mutex.Unlock();
00432 return TRUE;
00433 }
00434 m_mutex.Unlock();
00435 return FALSE;
00436 }
00437
00438
00439
00446 BOOL
00447 CThread::Push( LPVOID lpv )
00448 {
00449 if( !lpv ) return TRUE;
00450
00451 m_mutex.Lock();
00452
00453 if( m_quePos+1 >= m_chQue ) {
00454 m_mutex.Unlock();
00455 return FALSE;
00456 }
00457
00458 m_lppvQue[m_quePos++] = lpv;
00459 m_mutex.Unlock();
00460 return TRUE;
00461 }
00462
00463
00470 BOOL
00471 CThread::Pop()
00472 {
00473
00474 m_mutex.Lock();
00475 if( (int)m_quePos-1 < 0 )
00476 {
00477 m_quePos = 0;
00478 m_mutex.Unlock();
00479 return FALSE;
00480 }
00481 m_quePos--;
00482 m_lpvProcessor = m_lppvQue[m_quePos];
00483 m_mutex.Unlock();
00484 return TRUE;
00485 }
00486
00487
00501 void
00502 CThread::SetThreadType(ThreadType_t typ,
00503 DWORD dwIdle)
00504 {
00505
00506 m_mutex.Lock();
00507 m_dwIdle = dwIdle;
00508
00509 if( m_type == typ ) {
00510 m_mutex.Unlock();
00511 return;
00512 }
00513
00514 m_type = typ;
00515
00516
00517 m_mutex.Unlock();
00518 m_event.Set();
00519 }
00520
00521
00528 void
00529 CThread::Stop()
00530 {
00531 m_mutex.Lock();
00532 m_bRunning = FALSE;
00533 m_mutex.Unlock();
00534 Event();
00535
00536 Sleep(m_dwIdle);
00537 while(TRUE)
00538 {
00539 m_mutex.Lock();
00540 if( m_state == ThreadStateDown )
00541 {
00542 m_mutex.Unlock();
00543 return;
00544 }
00545 m_mutex.Unlock();
00546 Sleep(m_dwIdle);
00547 }
00548 }
00549
00550
00557 void
00558 CThread::SetIdle(DWORD dwIdle)
00559 {
00560 m_mutex.Lock();
00561 m_dwIdle = dwIdle;
00562 m_mutex.Unlock();
00563 }
00564
00571 BOOL
00572 CThread::Start()
00573 {
00574 m_mutex.Lock();
00575 if( m_bRunning )
00576 {
00577 m_mutex.Unlock();
00578 return TRUE;
00579 }
00580
00581 m_mutex.Unlock();
00582
00583
00584 if( m_dwObjectCondition & THREAD_CREATION )
00585 m_dwObjectCondition = m_dwObjectCondition ^ THREAD_CREATION;
00586
00587 #ifdef WINDOWS
00588 if( m_thread ) CloseHandle(m_thread);
00589
00590 m_thread = CreateThread(NULL,m_stackSize ,_THKERNEL,(LPVOID)this,0,&m_dwId);
00591 if( !m_thread )
00592 {
00593 perror("thread creating failed");
00594 m_dwObjectCondition |= THREAD_CREATION;
00595 m_state = ThreadStateFault;
00596 return FALSE;
00597 }
00598 #else
00599 pthread_attr_t attr;
00600
00601 pthread_attr_init(&attr);
00602
00603 #ifdef VMS
00604 if( m_stackSize == 0 )
00605 pthread_attr_setstacksize(&attr,PTHREAD_STACK_MIN*10);
00606 #endif
00607 if( m_stackSize != 0 )
00608 pthread_attr_setstacksize(&attr,m_stackSize);
00609
00610 int error = pthread_create(&m_thread,&attr,_THKERNEL,(LPVOID)this);
00611
00612 if( error != 0 )
00613 {
00614 m_dwObjectCondition |= THREAD_CREATION;
00615 m_state = ThreadStateFault;
00616
00617 #if defined(HPUX) || defined(SUNOS) || defined(LINUX)
00618 switch(error)
00619 {
00620
00621 case EINVAL:
00622 cerr << "error: attr in an invalid thread attributes object\n";
00623 break;
00624 case EAGAIN:
00625 cerr << "error: the necessary resources to create a thread are not\n";
00626 cerr << "available.\n";
00627 break;
00628 case EPERM:
00629 cerr << "error: the caller does not have the privileges to create\n";
00630 cerr << "the thread with the specified attr object.\n";
00631 break;
00632 #if defined(HPUX)
00633 case ENOSYS:
00634
00635 cerr << "error: pthread_create not implemented!\n";
00636 if( __is_threadlib_linked()==0 )
00637 {
00638 cerr << "error: threaded library not being used, improper linkage \"-lpthread -lc\"!\n";
00639 }
00640 break;
00641 #endif
00642 default:
00643 cerr << "error: an unknown error was encountered attempting to create\n";
00644 cerr << "the requested thread.\n";
00645 break;
00646 }
00647 #else
00648 cerr << "error: could not create thread, pthread_create failed (" << error << ")!\n";
00649 #endif
00650 return FALSE;
00651 }
00652 #endif
00653 return TRUE;
00654 }
00655
00656
00663 ThreadState_t
00664 CThread::ThreadState()
00665 {
00666 ThreadState_t currentState;
00667 m_mutex.Lock();
00668 currentState = m_state;
00669 m_mutex.Unlock();
00670 return currentState;
00671 }
00672
00680 CThread::~CThread(void)
00681 {
00682 #ifdef WINDOWS
00683 if( m_bRunning )
00684 {
00685
00686 Stop();
00687 WaitForSingleObject(m_thread,INFINITE);
00688
00689 }
00690 CloseHandle(m_thread);
00691 #else
00692 LPVOID lpv;
00693
00694 if( m_bRunning )
00695 {
00696 Stop();
00697 pthread_join(m_thread,&lpv);
00698 }
00699 #endif
00700
00701 delete [] m_lppvQue;
00702 }
00703
00704
00711 BOOL
00712 CThread::PingThread(DWORD dwTimeout
00713 )
00714 {
00715 DWORD dwTotal = 0;
00716
00717 while(TRUE)
00718 {
00719 if( dwTotal > dwTimeout && dwTimeout > 0 )
00720 return FALSE;
00721 m_mutex.Lock();
00722 if( m_bRunning )
00723 {
00724 m_mutex.Unlock();
00725 return TRUE;
00726 }
00727 dwTotal += m_dwIdle;
00728 m_mutex.Unlock();
00729 Sleep(m_dwIdle);
00730 }
00731
00732 return FALSE;
00733 }
00734
00735
00736
00737