void ThreadPool::queueWorkItem( WorkItem* item ) { bool executeRightAway = ( getForceAllMainThread() ); #ifdef DEBUG_SPEW Platform::outputDebugString( "[ThreadPool] %s work item '0x%x'", ( executeRightAway ? "executing" : "queuing" ), item ); #endif if( executeRightAway ) item->process(); else { // Put the item in the queue. mWorkItemQueue.insert( item->getPriority(), item ); // Wake up some thread, if we need to. // Use the ready count here as the wake count does // not correctly protect the critical section in the // thread's run function. This may lead us to release // the semaphore more often than necessary, but it avoids // a race condition. if( !dCompareAndSwap( mNumThreadsReady, mNumThreads, mNumThreads ) ) mSemaphore.release(); } }
UTF16* utf16() const { if( !mUTF16 ) { // Do this atomically to protect interned strings. UTF16* utf16 = convertUTF8toUTF16( mData ); if( !dCompareAndSwap( mUTF16,( UTF16* ) NULL, utf16 ) ) delete [] utf16; } return mUTF16; }
//----------------------------------------------------------------------------- // Function: ThreadRunHandler // Summary: Calls Thread::run() with the thread's specified run argument. // Neccesary because Thread::run() is provided as a non-threaded // way to execute the thread's run function. So we have to keep // track of the thread's lock here. static unsigned int __stdcall ThreadRunHandler(void * arg) { PlatformThreadData* mData = reinterpret_cast<PlatformThreadData*>(arg); mData->mThreadID = GetCurrentThreadId(); ThreadManager::addThread(mData->mThread); mData->mThread->run(mData->mRunArg); ThreadManager::removeThread(mData->mThread); bool autoDelete = mData->mThread->autoDelete; mData->mThreadHnd = NULL; // mark as dead dCompareAndSwap( mData->mDead, false, true ); mData->mGateway.release(); // don't access data after this. if( autoDelete ) delete mData->mThread; // Safe as we own the data. _endthreadex( 0 ); return 0; }
U32 OggVorbisDecoder::read( RawData** buffer, U32 num ) { #ifdef TORQUE_DEBUG AssertFatal( dCompareAndSwap( mLock, 0, 1 ), "OggVorbisDecoder::read() - simultaneous reads not thread-safe" ); #endif U32 numRead = 0; for( U32 i = 0; i < num; ++ i ) { float** pcmData; U32 numSamples; // Read sample data. while( 1 ) { numSamples = vorbis_synthesis_pcmout( &mVorbisDspState, &pcmData ); if( numSamples ) break; else { if( !_nextPacket() ) return numRead; // End of stream. vorbis_synthesis_blockin( &mVorbisDspState, &mVorbisBlock ); } } vorbis_synthesis_read( &mVorbisDspState, numSamples ); #ifdef DEBUG_SPEW Platform::outputDebugString( "[OggVorbisDecoder] read %i samples", numSamples ); #endif // Allocate a packet. const U32 numChannels = getNumChannels(); RawData* packet = constructSingle< RawData* >( numSamples * 2 * numChannels ); // Two bytes per channel. // Convert and copy the samples. S16* samplePtr = ( S16* ) packet->data; for( U32 n = 0; n < numSamples; ++ n ) for( U32 c = 0; c < numChannels; ++ c ) { S32 val = S32( pcmData[ c ][ n ] * 32767.f ); if( val > 32767 ) val = 32767; else if( val < -34768 ) val = -32768; *samplePtr = val; ++ samplePtr; } // Success. buffer[ i ] = packet; numRead ++; } #ifdef TORQUE_DEBUG AssertFatal( dCompareAndSwap( mLock, 1, 0 ), "" ); #endif return numRead; }