Alex Bikfalvi
SimWorker Documentation
SimWorker.cpp
00001 #include "Headers.h" 00002 #include "SimWorker.h" 00003 #include "ExceptionWorker.h" 00004 #include "ExceptionThread.h" 00005 #include "ExceptionSignal.h" 00006 #include "ExceptionMutex.h" 00007 00008 CSimWorker::CSimWorker( 00009 unsigned int id, 00010 unsigned int queueSize 00011 ) 00012 { 00013 this->id = id; 00014 this->queueSize = queueSize; 00015 this->queueCount = 0; 00016 this->queuePtr = 0; 00017 00018 // Create queue 00019 this->queue = new CSimWorkItem*[this->queueSize]; 00020 00021 // Initial state 00022 this->state = WORKER_STATE_STOPPED; 00023 00024 #ifdef WIN32 00025 // Initialize the thread mutex 00026 InitializeCriticalSection(&this->threadMutex); 00027 00028 // Initialize the state signal 00029 if(NULL == (this->stateHandle = CreateEvent( 00030 NULL, // default security attributes 00031 false, // manual reset 00032 false, // initial state (true is signaled) 00033 NULL // event name 00034 ))) throw CExceptionSignal("create state signal failed", __FILE__, __LINE__); 00035 00036 // Initialize the work signal 00037 if(NULL == (this->workHandle = CreateEvent( 00038 NULL, // default security attributes 00039 false, // manual reset 00040 false, // initial state (true is signaled) 00041 NULL // event name 00042 ))) throw CExceptionSignal("create work signal failed", __FILE__, __LINE__); 00043 00044 #elif POSIX 00045 // Initialize the thread mutex 00046 if(pthread_mutex_init(&this->threadMutex, NULL)) throw CExceptionMutex("create thread mutex failed", __FILE__, __LINE__); 00047 00048 // Initialize the state mutex 00049 if(pthread_mutex_init(&this->stateMutex, NULL)) throw CExceptionMutex("create state mutex failed", __FILE__, __LINE__); 00050 // Initialize the state codition 00051 if(pthread_cond_init(&this->stateCond, NULL)) throw CExceptionSignal("create state signal failed", __FILE__, __LINE__); 00052 00053 // Initialize the work mutex 00054 if(pthread_mutex_init(&this->workMutex, NULL)) throw CExceptionMutex("create work mutex failed", __FILE__, __LINE__); 00055 // Initialize the work codition 00056 if(pthread_cond_init(&this->workCond, NULL)) throw CExceptionSignal("create work signal failed", __FILE__, __LINE__); 00057 #endif 00058 } 00059 00060 CSimWorker::~CSimWorker() 00061 { 00062 #ifdef WIN32 00063 // Close the thread mutex 00064 DeleteCriticalSection(&this->threadMutex); 00065 00066 // Close the state signal 00067 if(!CloseHandle(this->stateHandle)) throw CExceptionSignal("close state signal failed", __FILE__, __LINE__); 00068 00069 // Close the work signal 00070 if(!CloseHandle(this->workHandle)) throw CExceptionSignal("close work signal failed", __FILE__, __LINE__); 00071 00072 #elif POSIX 00073 // Close the thread mutex 00074 if(pthread_mutex_destroy(&this->threadMutex)) throw CExceptionMutex("close thread mutex failed", __FILE__, __LINE__); 00075 00076 // Close the state condition 00077 if(pthread_cond_destroy(&this->stateCond)) throw CExceptionSignal("close state signal failed", __FILE__, __LINE__); 00078 // Close the state mutex 00079 if(pthread_mutex_destroy(&this->stateMutex)) throw CExceptionMutex("close state mutex failed", __FILE__, __LINE__); 00080 00081 // Close the work condition 00082 if(pthread_cond_destroy(&this->workCond)) throw CExceptionSignal("close work signal failed", __FILE__, __LINE__); 00083 // Close the work mutex 00084 if(pthread_mutex_destroy(&this->workMutex)) throw CExceptionMutex("close work mutex failed", __FILE__, __LINE__); 00085 #endif 00086 00087 // Delete queue 00088 delete[] this->queue; 00089 } 00090 00091 void CSimWorker::Start() 00092 { 00093 #ifdef WIN32 00094 // Lock the thread mutex 00095 EnterCriticalSection(&this->threadMutex); 00096 try 00097 { 00098 // Check the worker state 00099 if(WORKER_STATE_STOPPED != this->state) throw CExceptionWorker("worker is not stopped", __FILE__, __LINE__, this->id); 00100 00101 // Change the worker state 00102 this->state = WORKER_STATE_STARTING; 00103 00104 // Start thread 00105 if(!(this->threadHandle = CreateThread( 00106 NULL, // default security attributes 00107 0, // default stack size 00108 &CSimWorker::Execute, // thread function address 00109 this, // parameter 00110 0, // creation flags 00111 &this->threadId // thread ID 00112 ))) throw CExceptionThread("create thread failed", __FILE__, __LINE__, this->threadId); 00113 } 00114 catch(...) 00115 { 00116 // Unlock the thread mutex and re-throw exception 00117 LeaveCriticalSection(&this->threadMutex); 00118 throw; 00119 } 00120 // Unlock the thread mutex 00121 LeaveCriticalSection(&this->threadMutex); 00122 00123 // Wait for thread to signal the state 00124 if(WAIT_FAILED == WaitForSingleObject(this->stateHandle, INFINITE)) throw CExceptionSignal("waiting for worker start signal failed", __FILE__, __LINE__); 00125 #elif POSIX 00126 // Lock the thread mutex 00127 if(pthread_mutex_lock(&this->threadMutex)) throw CExceptionMutex("locking thread mutex failed", __FILE__, __LINE__); 00128 // Lock the state mutex 00129 if(pthread_mutex_lock(&this->stateMutex)) throw CExceptionMutex("locking state mutex failed", __FILE__, __LINE__); 00130 try 00131 { 00132 // Check the worker state 00133 if(WORKER_STATE_STOPPED != this->state) throw CExceptionWorker("worker is not stopped", __FILE__, __LINE__, this->id); 00134 00135 // Change the worker state 00136 this->state = WORKER_STATE_STARTING; 00137 00138 if(pthread_create( 00139 &this->threadHandle, // thread handle 00140 NULL, // default thread attribute 00141 &CSimWorker::Execute, // thread function address 00142 (void*)this // parameter 00143 )) throw CExceptionThread("create thread failed", __FILE__, __LINE__, this->threadHandle); 00144 00145 #ifdef WORKER_PRIORITY 00146 struct sched_param schedParam; 00147 int schedPolicy; 00148 00149 pthread_getschedparam(this->threadHandle, &schedPolicy, &schedParam); 00150 00151 int schedPriorityMax = sched_get_priority_max(schedPolicy); 00152 int schedPriorityMin = sched_get_priority_min(schedPolicy); 00153 00154 cout << endl; 00155 cout << "Thread policy is: " << schedPolicy << endl; 00156 cout << "Thread priority is: " << schedParam.__sched_priority << endl; 00157 cout << "Scheduling policy priority range is: " << schedPriorityMin << ".." << schedPriorityMax << endl; 00158 cout << "Changing thread priority to real-time: "; 00159 00160 schedParam.__sched_priority = 1; 00161 switch(pthread_setschedparam(this->threadHandle, SCHED_FIFO, &schedParam)) 00162 { 00163 case EINVAL: cout << "invalid policy or parameter." << endl; break; 00164 case ENOTSUP: cout << "not supported." << endl; break; 00165 case EPERM: cout << "no permissions." << endl; break; 00166 case ESRCH: cout << "thread does not exist." << endl; break; 00167 default: cout << "success." << endl; 00168 } 00169 #endif 00170 } 00171 catch(...) 00172 { 00173 // Unlock the thread mutex and re-throw exception 00174 if(pthread_mutex_unlock(&this->threadMutex)) throw CExceptionMutex("unlocking thread mutex failed", __FILE__, __LINE__); 00175 throw; 00176 } 00177 // Unlock the thread mutex 00178 if(pthread_mutex_unlock(&this->threadMutex)) throw CExceptionMutex("unlocking thread mutex failed", __FILE__, __LINE__); 00179 00180 // Wait for thread to signal the state 00181 if(pthread_cond_wait(&this->stateCond, &this->stateMutex)) throw CExceptionSignal("waiting for worker start signal failed", __FILE__, __LINE__); 00182 #endif 00183 } 00184 00185 void CSimWorker::Stop() 00186 { 00187 #ifdef WIN32 00188 // Lock the thread mutex 00189 EnterCriticalSection(&this->threadMutex); 00190 try 00191 { 00192 // Check the worker state 00193 if((WORKER_STATE_STARTED_IDLE != this->state) && (WORKER_STATE_STARTED_BUSY != this->state)) 00194 throw CExceptionWorker("worker is not started", __FILE__, __LINE__, this->id); 00195 00196 // Save the old worker state 00197 EWorkerState oldState = this->state; 00198 00199 // Change the worker state 00200 this->state = WORKER_STATE_STOPPING; 00201 00202 // Send work change signal 00203 if(!SetEvent(this->workHandle)) throw CExceptionSignal("set work signal to signaled state failed", __FILE__, __LINE__); 00204 } 00205 catch(...) 00206 { 00207 // Unlock the thread mutex and re-throw exception 00208 LeaveCriticalSection(&this->threadMutex); 00209 throw; 00210 } 00211 // Unlock the thread mutex 00212 LeaveCriticalSection(&this->threadMutex); 00213 00214 // Wait for thread to complete 00215 if(WAIT_FAILED == WaitForSingleObject(this->threadHandle, INFINITE)) throw CExceptionSignal("waiting for worker stop signal failed", __FILE__, __LINE__); 00216 00217 // Close the thread handle 00218 if(!CloseHandle(this->threadHandle)) throw CExceptionThread("close thread failed", __FILE__, __LINE__, this->threadId); 00219 00220 #elif POSIX 00221 // Lock the thread mutex 00222 if(pthread_mutex_lock(&this->threadMutex)) throw CExceptionMutex("locking thread mutex failed", __FILE__, __LINE__); 00223 try 00224 { 00225 // Check the worker state 00226 if((WORKER_STATE_STARTED_IDLE != this->state) && (WORKER_STATE_STARTED_BUSY != this->state)) 00227 throw CExceptionWorker("worker is not started", __FILE__, __LINE__, this->id); 00228 00229 // Save the old worker state 00230 EWorkerState oldState = this->state; 00231 00232 // Change the worker state 00233 this->state = WORKER_STATE_STOPPING; 00234 00235 // If can acquire a lock on the work mutex 00236 if(!pthread_mutex_trylock(&this->workMutex)) 00237 { 00238 try 00239 { 00240 // Send work signal 00241 if(pthread_cond_signal(&this->workCond)) throw CExceptionSignal("set work signal to signaled state failed", __FILE__, __LINE__); 00242 } 00243 catch(...) 00244 { 00245 // Unlock the work mutex and re-throw the exception 00246 if(pthread_mutex_unlock(&this->workMutex)) throw CExceptionMutex("unlocking work mutex failed", __FILE__, __LINE__); 00247 throw; 00248 } 00249 // Unlock the work mutex 00250 if(pthread_mutex_unlock(&this->workMutex)) throw CExceptionMutex("unlocking work mutex failed", __FILE__, __LINE__); 00251 } 00252 } 00253 catch(...) 00254 { 00255 // Unlock the thread mutex and re-throw exception 00256 if(pthread_mutex_unlock(&this->threadMutex)) throw CExceptionMutex("unlocking thread mutex failed", __FILE__, __LINE__); 00257 throw; 00258 } 00259 // Unlock the thread mutex 00260 if(pthread_mutex_unlock(&this->threadMutex)) throw CExceptionMutex("unlocking thread mutex failed", __FILE__, __LINE__); 00261 00262 // Wait for thread to complete 00263 if(pthread_join(this->threadHandle, NULL)) throw CExceptionSignal("waiting for worker stop signal failed", __FILE__, __LINE__); 00264 // Unlock the state mutex 00265 if(pthread_mutex_unlock(&this->stateMutex)) throw CExceptionMutex("unlocking the state mutex failed", __FILE__, __LINE__); 00266 #endif 00267 } 00268 00269 void CSimWorker::Enqueue(CSimWorkItem* item) 00270 { 00271 #ifdef WIN32 00272 // Synchronize access to shared variables 00273 EnterCriticalSection(&this->threadMutex); 00274 try 00275 { 00276 // Check the worker state 00277 if((WORKER_STATE_STARTED_IDLE != this->state) && (WORKER_STATE_STARTED_BUSY != this->state)) throw CExceptionWorker("cannot enqueue item; worker to started", __FILE__, __LINE__, this->id); 00278 00279 // Check the worker queue is not empty 00280 if(this->queueCount >= this->queueSize) throw CExceptionWorker("worker queue is full", __FILE__, __LINE__, this->id); 00281 00282 // Add the work item to the queue 00283 this->queue[(this->queuePtr + this->queueCount) % this->queueSize] = item; 00284 this->queueCount++; 00285 00286 // If the worker is in idle, send work change signal 00287 if(WORKER_STATE_STARTED_IDLE == this->state) 00288 if(!SetEvent(this->workHandle)) throw CExceptionSignal("set work signal to signaled state failed", __FILE__, __LINE__); 00289 } 00290 catch(...) 00291 { 00292 LeaveCriticalSection(&this->threadMutex); 00293 throw; 00294 } 00295 LeaveCriticalSection(&this->threadMutex); 00296 #elif POSIX 00297 // Synchronize access to shared variables 00298 if(pthread_mutex_lock(&this->threadMutex)) throw CExceptionMutex("locking thread mutex failed", __FILE__, __LINE__); 00299 try 00300 { 00301 // Check the worker state 00302 if((WORKER_STATE_STARTED_IDLE != this->state) && (WORKER_STATE_STARTED_BUSY != this->state)) throw CExceptionWorker("cannot enqueue item; worker to started", __FILE__, __LINE__, this->id); 00303 00304 // Check the worker queue is not empty 00305 if(this->queueCount >= this->queueSize) throw CExceptionWorker("worker queue is full", __FILE__, __LINE__, this->id); 00306 00307 // Add the work item to the queue 00308 this->queue[(this->queuePtr + this->queueCount) % this->queueSize] = item; 00309 this->queueCount++; 00310 00311 // If can acquire a lock on the work mutex 00312 if(!pthread_mutex_trylock(&this->workMutex)) 00313 { 00314 try 00315 { 00316 // Send work signal 00317 if(pthread_cond_signal(&this->workCond)) throw CExceptionSignal("set work signal to signaled state failed", __FILE__, __LINE__); 00318 } 00319 catch(...) 00320 { 00321 // Unlock the work mutex and re-throw the exception 00322 if(pthread_mutex_unlock(&this->workMutex)) throw CExceptionMutex("unlocking work mutex failed", __FILE__, __LINE__); 00323 throw; 00324 } 00325 // Unlock the work mutex 00326 if(pthread_mutex_unlock(&this->workMutex)) throw CExceptionMutex("unlocking work mutex failed", __FILE__, __LINE__); 00327 } 00328 } 00329 catch(...) 00330 { 00331 if(pthread_mutex_unlock(&this->threadMutex)) throw CExceptionMutex("unlocking thread mutex failed", __FILE__, __LINE__); 00332 throw; 00333 } 00334 if(pthread_mutex_unlock(&this->threadMutex)) throw CExceptionMutex("unlocking thread mutex failed", __FILE__, __LINE__); 00335 #endif 00336 } 00337 00338 #ifdef WIN32 00339 DWORD CSimWorker::Execute(__in LPVOID parameter) 00340 { 00341 // Get the object 00342 CSimWorker* worker = (CSimWorker*)(parameter); 00343 00344 // Synchronize access to shared variables 00345 EnterCriticalSection(&worker->threadMutex); 00346 try 00347 { 00348 // Change the state 00349 worker->state = WORKER_STATE_STARTED_IDLE; 00350 00351 // Send state change signal 00352 if(!SetEvent(worker->stateHandle)) throw CExceptionSignal("set state signal to signaled state failed", __FILE__, __LINE__); 00353 } 00354 catch(...) 00355 { 00356 LeaveCriticalSection(&worker->threadMutex); 00357 throw; 00358 } 00359 LeaveCriticalSection(&worker->threadMutex); 00360 00361 // Worker execution loop 00362 do 00363 { 00364 // Wait for a work signal 00365 if(WAIT_FAILED == WaitForSingleObject(worker->workHandle, INFINITE)) throw CExceptionSignal("waiting for work signal failed", __FILE__, __LINE__); 00366 00367 // Local copy of the work item 00368 CSimWorkItem* item = NULL; 00369 00370 do 00371 { 00372 // Synchronize access to shared variables 00373 EnterCriticalSection(&worker->threadMutex); 00374 try 00375 { 00376 // If the worker is not stopping and the worker queue is not empty 00377 if(WORKER_STATE_STOPPING != worker->state) 00378 { 00379 if(worker->queueCount) 00380 { 00381 // Pop the oldest work item from the queue 00382 item = worker->queue[worker->queuePtr]; 00383 00384 // Shift the end of the queue 00385 worker->queuePtr = (++worker->queuePtr) % worker->queueSize; 00386 worker->queueCount--; 00387 00388 // Set worker state to busy 00389 worker->state = WORKER_STATE_STARTED_BUSY; 00390 } 00391 else 00392 { 00393 // Set item to null 00394 item = NULL; 00395 00396 // Set worker state to idle 00397 worker->state = WORKER_STATE_STARTED_IDLE; 00398 } 00399 } 00400 } 00401 catch(...) 00402 { 00403 LeaveCriticalSection(&worker->threadMutex); 00404 throw; 00405 } 00406 LeaveCriticalSection(&worker->threadMutex); 00407 00408 // If the work item is not null 00409 if(item && (WORKER_STATE_STOPPING != worker->state)) 00410 { 00411 try 00412 { 00413 // Execute the work item 00414 item->Execute(); 00415 00416 // Signal work item completion : success 00417 item->Signal(CSimWorkItem::COMPLETED_SUCCESS); 00418 } 00419 catch(...) 00420 { 00421 // Signal work item completion : fail 00422 item->Signal(CSimWorkItem::COMPLETED_FAIL); 00423 } 00424 } 00425 } 00426 while(item && (WORKER_STATE_STOPPING != worker->state)); 00427 00428 } 00429 while(WORKER_STATE_STOPPING != worker->state); 00430 00431 // Synchronize access to shared variables 00432 EnterCriticalSection(&worker->threadMutex); 00433 try 00434 { 00435 // Change worker state 00436 worker->state = WORKER_STATE_STOPPED; 00437 00438 // Signal all work items remaining in the queue 00439 for(; worker->queueCount; worker->queueCount--) 00440 { 00441 // Pop item from the queue 00442 CSimWorkItem* item = worker->queue[worker->queuePtr]; 00443 00444 // Shift the end of the queue 00445 worker->queuePtr = (++worker->queuePtr) % worker->queueSize; 00446 00447 // Signal work item completion : pending 00448 item->Signal(CSimWorkItem::PENDING); 00449 } 00450 } 00451 catch(...) 00452 { 00453 LeaveCriticalSection(&worker->threadMutex); 00454 throw; 00455 } 00456 LeaveCriticalSection(&worker->threadMutex); 00457 00458 return 0; 00459 } 00460 #elif POSIX 00461 void* CSimWorker::Execute(void* parameter) 00462 { 00463 // Get the object 00464 CSimWorker* worker = (CSimWorker*)(parameter); 00465 00466 // Lock the work mutex 00467 if(pthread_mutex_lock(&worker->workMutex)) throw CExceptionMutex("locking work mutex failed", __FILE__, __LINE__); 00468 00469 try 00470 { 00471 // Synchronize access to shared variables 00472 if(pthread_mutex_lock(&worker->threadMutex)) throw CExceptionMutex("locking thread mutex failed", __FILE__, __LINE__); 00473 try 00474 { 00475 // Change the state 00476 worker->state = WORKER_STATE_STARTED_IDLE; 00477 00478 // Send state change signal 00479 00480 // Lock the state mutex 00481 if(pthread_mutex_lock(&worker->stateMutex)) throw CExceptionMutex("locking state mutex failed", __FILE__, __LINE__); 00482 try 00483 { 00484 // Send signal 00485 if(pthread_cond_signal(&worker->stateCond)) throw CExceptionSignal("set state signal to signaled state failed", __FILE__, __LINE__); 00486 } 00487 catch(...) 00488 { 00489 // Unlock the state mutex 00490 if(pthread_mutex_unlock(&worker->stateMutex)) throw CExceptionMutex("unlocking state mutex failed", __FILE__, __LINE__); 00491 throw; 00492 } 00493 if(pthread_mutex_unlock(&worker->stateMutex)) throw CExceptionMutex("unlocking state mutex failed", __FILE__, __LINE__); 00494 } 00495 catch(...) 00496 { 00497 if(pthread_mutex_unlock(&worker->threadMutex)) throw CExceptionMutex("unlocking thread mutex failed", __FILE__, __LINE__); 00498 throw; 00499 } 00500 if(pthread_mutex_unlock(&worker->threadMutex)) throw CExceptionMutex("unlocking thread mutex failed", __FILE__, __LINE__); 00501 00502 // Worker execution loop 00503 do 00504 { 00505 // Wait for a work signal 00506 if(pthread_cond_wait(&worker->workCond, &worker->workMutex)) throw CExceptionSignal("waiting for work signal failed", __FILE__, __LINE__); 00507 00508 // Local copy of the work item 00509 CSimWorkItem* item = NULL; 00510 00511 do 00512 { 00513 // Synchronize access to shared variables 00514 if(pthread_mutex_lock(&worker->threadMutex)) throw CExceptionMutex("locking thread mutex failed", __FILE__, __LINE__); 00515 try 00516 { 00517 // If the worker is not stopping and the worker queue is not empty 00518 if(WORKER_STATE_STOPPING != worker->state) 00519 { 00520 if(worker->queueCount) 00521 { 00522 // Pop the oldest work item from the queue 00523 item = worker->queue[worker->queuePtr]; 00524 00525 // Shift the end of the queue 00526 worker->queuePtr = (++worker->queuePtr) % worker->queueSize; 00527 worker->queueCount--; 00528 00529 // Set worker state to busy 00530 worker->state = WORKER_STATE_STARTED_BUSY; 00531 } 00532 else 00533 { 00534 // Set item to null 00535 item = NULL; 00536 00537 // Set worker state to idle 00538 worker->state = WORKER_STATE_STARTED_IDLE; 00539 } 00540 } 00541 } 00542 catch(...) 00543 { 00544 if(pthread_mutex_unlock(&worker->threadMutex)) throw CExceptionMutex("unlocking thread mutex failed", __FILE__, __LINE__); 00545 throw; 00546 } 00547 if(pthread_mutex_unlock(&worker->threadMutex)) throw CExceptionMutex("unlocking thread mutex failed", __FILE__, __LINE__); 00548 00549 // If the work item is not null 00550 if(item && (WORKER_STATE_STOPPING != worker->state)) 00551 { 00552 try 00553 { 00554 // Execute the work item 00555 item->Execute(); 00556 00557 // Signal work item completion : success 00558 item->Signal(CSimWorkItem::COMPLETED_SUCCESS); 00559 } 00560 catch(...) 00561 { 00562 // Signal work item completion : fail 00563 item->Signal(CSimWorkItem::COMPLETED_FAIL); 00564 } 00565 } 00566 } 00567 while(item && (WORKER_STATE_STOPPING != worker->state)); 00568 00569 } 00570 while(WORKER_STATE_STOPPING != worker->state); 00571 00572 // Synchronize access to shared variables 00573 if(pthread_mutex_lock(&worker->threadMutex)) throw CExceptionMutex("locking thread mutex failed", __FILE__, __LINE__); 00574 try 00575 { 00576 // Change worker state 00577 worker->state = WORKER_STATE_STOPPED; 00578 00579 // Signal all work items remaining in the queue 00580 for(; worker->queueCount; worker->queueCount--) 00581 { 00582 // Pop item from the queue 00583 CSimWorkItem* item = worker->queue[worker->queuePtr]; 00584 00585 // Shift the end of the queue 00586 worker->queuePtr = (++worker->queuePtr) % worker->queueSize; 00587 00588 // Signal work item completion : pending 00589 item->Signal(CSimWorkItem::PENDING); 00590 } 00591 } 00592 catch(...) 00593 { 00594 if(pthread_mutex_unlock(&worker->threadMutex)) throw CExceptionMutex("unlocking thread mutex failed", __FILE__, __LINE__); 00595 throw; 00596 } 00597 if(pthread_mutex_unlock(&worker->threadMutex)) throw CExceptionMutex("unlocking thread mutex failed", __FILE__, __LINE__); 00598 } 00599 catch(...) 00600 { 00601 // Unlock the work mutex and re-throw exception 00602 if(pthread_mutex_unlock(&worker->workMutex)) throw CExceptionMutex("unlocking work mutex failed", __FILE__, __LINE__); 00603 throw; 00604 } 00605 // Unlock the work mutex 00606 if(pthread_mutex_unlock(&worker->workMutex)) throw CExceptionMutex("unlocking work mutex failed", __FILE__, __LINE__); 00607 00608 return 0; 00609 } 00610 #endif
Last updated: February 8, 2011