| 230 | } |
| 231 | |
| 232 | void ThreadPool::WorkerThread::run( void* arg ) |
| 233 | { |
| 234 | #ifdef TORQUE_DEBUG |
| 235 | { |
| 236 | // Set the thread's name for debugging. |
| 237 | char buffer[ 2048 ]; |
| 238 | dSprintf( buffer, sizeof( buffer ), "ThreadPool(%s) WorkerThread %i", mPool->mName.c_str(), mIndex ); |
| 239 | _setName( buffer ); |
| 240 | } |
| 241 | #endif |
| 242 | |
| 243 | while( 1 ) |
| 244 | { |
| 245 | if( checkForStop() ) |
| 246 | { |
| 247 | #ifdef DEBUG_SPEW |
| 248 | Platform::outputDebugString( "[ThreadPool::WorkerThread] thread '%i' exits", getId() ); |
| 249 | #endif |
| 250 | dFetchAndAdd( mPool->mNumThreads, ( U32 ) -1 ); |
| 251 | return; |
| 252 | } |
| 253 | |
| 254 | // Mark us as potentially blocking. |
| 255 | dFetchAndAdd( mPool->mNumThreadsReady, ( U32 ) -1 ); |
| 256 | |
| 257 | bool waitForSignal = false; |
| 258 | { |
| 259 | // Try to take an item from the queue. Do |
| 260 | // this in a separate block, so we'll be |
| 261 | // releasing the item after we have finished. |
| 262 | |
| 263 | WorkItemWrapper workItem; |
| 264 | if( mPool->mWorkItemQueue.takeNext( workItem ) ) |
| 265 | { |
| 266 | // Mark us as non-blocking as this loop definitely |
| 267 | // won't wait on the semaphore. |
| 268 | dFetchAndAdd( mPool->mNumThreadsReady, 1 ); |
| 269 | |
| 270 | #ifdef DEBUG_SPEW |
| 271 | Platform::outputDebugString( "[ThreadPool::WorkerThread] thread '%i' takes item '0x%x'", getId(), *workItem ); |
| 272 | #endif |
| 273 | workItem->process(); |
| 274 | |
| 275 | dFetchAndAdd( mPool->mNumPendingItems, ( U32 ) -1 ); |
| 276 | } |
| 277 | else |
| 278 | waitForSignal = true; |
| 279 | } |
| 280 | |
| 281 | if( waitForSignal ) |
| 282 | { |
| 283 | dFetchAndAdd( mPool->mNumThreadsAwake, ( U32 ) -1 ); |
| 284 | |
| 285 | #ifdef DEBUG_SPEW |
| 286 | Platform::outputDebugString( "[ThreadPool::WorkerThread] thread '%i' going to sleep", getId() ); |
| 287 | #endif |
| 288 | mPool->mSemaphore.acquire(); |
| 289 | #ifdef DEBUG_SPEW |