static void process_request_queue( channel_t *ch ) { /* if somebody is already processing requests, increasing ring_lock * will cause an extra iteration (thus other request _will_ be handled). */ if( IncrementAtomic( &ch->ring_lock ) ) return; do { request_t *r; while( (r=(request_t*)dequeue(&ch->req_queue)) ) if( process_request( ch, r ) ) break; } while( DecrementAtomic(&ch->ring_lock) > 1 ); }
static void callBackProc(SndChannel * chan, SndCommand * cmd_passed) { UInt32 play_me; SndCommand cmd; SDL_AudioDevice *audio = (SDL_AudioDevice *) chan->userInfo; IncrementAtomic((SInt32 *) & need_to_mix); fill_me = cmd_passed->param2; /* buffer that has just finished playing, so fill it */ play_me = !fill_me; /* filled buffer to play _now_ */ if (!audio->enabled) { return; } /* queue previously mixed buffer for playback. */ header.samplePtr = (Ptr) buffer[play_me]; cmd.cmd = bufferCmd; cmd.param1 = 0; cmd.param2 = (long) &header; SndDoCommand(chan, &cmd, 0); SDL_memset(buffer[fill_me], 0, audio->spec.size); /* * if audio device isn't locked, mix the next buffer to be queued in * the memory block that just finished playing. */ if (!BitAndAtomic(0xFFFFFFFF, (UInt32 *) & audio_is_locked)) { mix_buffer(audio, buffer[fill_me]); } /* set this callback to run again when current buffer drains. */ if (running) { cmd.cmd = callBackCmd; cmd.param1 = 0; cmd.param2 = play_me; SndDoCommand(chan, &cmd, 0); } }
wxCondError wxConditionInternal::WaitTimeout( unsigned long milliseconds ) { IncrementAtomic( &m_numWaiters ); m_mutex.Unlock(); // a race condition can occur at this point in the code // // please see the comments in Wait(), for details wxSemaError err = m_semaphore.WaitTimeout(milliseconds); if ( err == wxSEMA_TIMEOUT ) { // another potential race condition exists here it is caused when a // 'waiting' thread timesout, and returns from WaitForSingleObject, but // has not yet decremented 'nwaiters'. // // at this point if another thread calls signal() then the semaphore // will be incremented, but the waiting thread will miss it. // // to handle this particular case, the waiting thread calls // WaitForSingleObject again with a timeout of 0, after locking // 'nwaiters_mutex'. this call does not block because of the zero // timeout, but will allow the waiting thread to catch the missed // signals. wxCriticalSectionLocker lock(m_csWaiters); err = m_semaphore.WaitTimeout(0); if ( err != wxSEMA_NO_ERROR ) { m_numWaiters--; } } m_mutex.Lock(); return err == wxSEMA_NO_ERROR ? wxCOND_NO_ERROR : wxCOND_MISC_ERROR; }
wxCondError wxConditionInternal::Wait() { // increment the number of waiters IncrementAtomic( &m_numWaiters ); m_mutex.Unlock(); // a potential race condition can occur here // // after a thread increments nwaiters, and unlocks the mutex and before the // semaphore.Wait() is called, if another thread can cause a signal to be // generated // // this race condition is handled by using a semaphore and incrementing the // semaphore only if 'nwaiters' is greater that zero since the semaphore, // can 'remember' signals the race condition will not occur // wait ( if necessary ) and decrement semaphore wxSemaError err = m_semaphore.Wait(); m_mutex.Lock(); return err == wxSEMA_NO_ERROR ? wxCOND_NO_ERROR : wxCOND_MISC_ERROR; }
static void Mac_LockAudio(_THIS) { IncrementAtomic((SInt32 *) &audio_is_locked); }
static void SNDMGR_LockDevice(_THIS) { IncrementAtomic((SInt32 *) & audio_is_locked); }
void retainWorkerThread ( WorkerThreadRef worker ) { if ( !worker ) return; IncrementAtomic( &worker->referenceCount ); }
void AddNeighborhoodToList(char * neighborhood, UInt32 parentID) { CFStringRef tempNeighborhood = NULL; CFComparisonResult result = -1; UInt32 neighborhoodID, i; if (neighborhood) { tempNeighborhood = CFStringCreateWithCString(NULL, neighborhood, CFStringGetSystemEncoding()); if (tempNeighborhood) { // Check if the item is already in our list. If it is, "result" will be kCFCompareEqualTo. for (i = 0; i < kMaxNeighborhoods; i++) { if (gData[i] && gNeighborhoodInfo.parentID[i] == parentID) { result = CFStringCompare(tempNeighborhood, gData[i], kCFCompareCaseInsensitive); if (result == kCFCompareEqualTo) break; } } if (result != kCFCompareEqualTo) { // Only add the item if the parent neighborhood is open and visible in the Data Browser. if ((gNeighborhoodInfo.isNeighborhoodOpen[parentID - 1] && gNeighborhoodInfo.isNeighborhoodVisible[parentID - 1]) || parentID == 0) { neighborhoodID = IncrementAtomic(&gNeighborhoodInfo.neighborhoodCount); if (++neighborhoodID < kMaxNeighborhoods) { gNeighborhoodInfo.parentID[neighborhoodID - 1] = parentID; gData[neighborhoodID - 1] = CFStringCreateCopy(NULL, tempNeighborhood); AddDataBrowserItems(gDataBrowserControl, parentID, 1, &neighborhoodID, kNameColumn); if (parentID == kDataBrowserNoItem) { gNeighborhoodInfo.isDefaultNeighborhood[neighborhoodID - 1] = true; } else { gNeighborhoodInfo.isDefaultNeighborhood[neighborhoodID - 1] = false; } } else { DecrementAtomic(&gNeighborhoodInfo.neighborhoodCount); } } } else if (result == kCFCompareEqualTo) { if (gNeighborhoodInfo.isNeighborhoodOpen[parentID - 1] && gNeighborhoodInfo.isNeighborhoodVisible[parentID - 1]) { neighborhoodID = i + 1; if (gNeighborhoodInfo.isNeighborhoodVisible[i] == false) { AddDataBrowserItems(gDataBrowserControl, parentID, 1, &neighborhoodID, kNameColumn); if (gNeighborhoodInfo.isNeighborhoodOpen[i]) { OpenDataBrowserContainer(gDataBrowserControl, neighborhoodID); } } else { if (gNeighborhoodInfo.isNeighborhoodOpen[i]) { CancelServicesLookup(parentID); CancelNeighborhoodLookup(parentID); InstallEventLoopTimer(GetMainEventLoop(), 0.3, 0, gMyStartLookupTimerUPP, (void *)(neighborhoodID), NULL); } } } } CFRelease(tempNeighborhood); } free(neighborhood); } }