void RethinkPlayers ( struct AHIDevUnit *iounit, struct AHIBase *AHIBase ) { struct MinList templist; struct AHIRequest *ioreq; NewList((struct List *) &templist); ObtainSemaphore(&iounit->ListLock); RemPlayers((struct List *) &iounit->PlayingList, iounit, AHIBase); RemPlayers((struct List *) &iounit->SilentList, iounit, AHIBase); // Move all silent requests to our temporary list while((ioreq = (struct AHIRequest *) RemHead((struct List *) &iounit->SilentList))) { AddTail((struct List *) &templist, (struct Node *) ioreq); } // And add them back... while((ioreq = (struct AHIRequest *) RemHead((struct List *) &templist))) { AddWriter(ioreq, iounit, AHIBase); } ReleaseSemaphore(&iounit->ListLock); }
bool CRWLockImpl::TryWriteLockImpl() { AddWriter(); HANDLE h[2]; h[0] = m_mutex; h[1] = m_writeEvent; switch (WaitForMultipleObjects(2, h, TRUE, 1)) { case WAIT_OBJECT_0: case WAIT_OBJECT_0 + 1: --m_writersWaiting; ++m_readers; ++m_writers; ResetEvent(m_readEvent); ResetEvent(m_writeEvent); ReleaseMutex(m_mutex); assert(m_writers == 1); return true; case WAIT_TIMEOUT: RemoveWriter(); default: RemoveWriter(); cout<<"cannot lock reader/writer lock"<<endl; } return false; }
void CRWLockImpl::WriteLockImpl() { AddWriter(); HANDLE h[2]; h[0] = m_mutex; h[1] = m_writeEvent; switch (WaitForMultipleObjects(2, h, TRUE, INFINITE)) { case WAIT_OBJECT_0: case WAIT_OBJECT_0 + 1: --m_writersWaiting; ++m_readers; ++m_writers; ResetEvent(m_readEvent); ResetEvent(m_writeEvent); ReleaseMutex(m_mutex); assert(m_writers == 1); break; default: RemoveWriter(); cout<<"cannot lock reader/writer lock"<<endl; } }
static void NewWriter ( struct AHIRequest *ioreq, struct AHIDevUnit *iounit, struct AHIBase *AHIBase ) { int channel, sound; BOOL delay = FALSE; struct AHISampleInfo si; struct Library *AHIsubBase; AHIsubBase = ((struct AHIPrivAudioCtrl *) iounit->AudioCtrl)->ahiac_SubLib; si.ahisi_Type = ioreq->ahir_Type; si.ahisi_Address = ioreq->ahir_Std.io_Data; si.ahisi_Length = ioreq->ahir_Std.io_Length; // Load the sound for(sound = 0; sound < MAXSOUNDS; sound++) { if(iounit->Sounds[sound] == SOUND_FREE) { iounit->Sounds[sound] = SOUND_IN_USE; break; } } if((sound < MAXSOUNDS) && (AHI_LoadSound(sound, AHIST_DYNAMICSAMPLE, &si, iounit->AudioCtrl) == AHIE_OK)) { GetExtras(ioreq)->Sound = sound; ObtainSemaphore(&iounit->ListLock); if(ioreq->ahir_Link) { // See if the linked request is playing, silent or waiting... if(FindNode((struct List *) &iounit->PlayingList, (struct Node *) ioreq->ahir_Link)) { delay = TRUE; } else if(FindNode((struct List *) &iounit->SilentList, (struct Node *) ioreq->ahir_Link)) { delay = TRUE; } else if(FindNode((struct List *) &iounit->WaitingList, (struct Node *) ioreq->ahir_Link)) { delay = TRUE; } } // NOTE: ahir_Link changes direction here. When the user set's it, she makes a new // request point to an old. We let the old point to the next (that's more natural, // anyway...) It the user tries to link more than one request to another, we fail. if(delay) { if( ! ioreq->ahir_Link->ahir_Link) { struct AHIRequest *otherioreq = ioreq->ahir_Link; channel = GetExtras(ioreq->ahir_Link)->Channel; GetExtras(ioreq)->Channel = NOCHANNEL; otherioreq->ahir_Link = ioreq; ioreq->ahir_Link = NULL; Enqueue((struct List *) &iounit->WaitingList,(struct Node *) ioreq); if(channel != NOCHANNEL) { // Attach the request to the currently playing one AHIsub_Disable((struct AHIAudioCtrlDrv *) iounit->AudioCtrl); // Make SURE the current sound isn't already finished! if(otherioreq->ahir_Std.io_Command == AHICMD_WRITTEN) { AHIsub_Enable((struct AHIAudioCtrlDrv *) iounit->AudioCtrl); // OOPS! It's finished! Undo... Remove((struct Node *) ioreq); // Start sound as if it wasn't delayed (see below); AddWriter(ioreq, iounit, AHIBase); } else { iounit->Voices[channel].QueuedRequest = ioreq; iounit->Voices[channel].NextOffset = PLAY; iounit->Voices[channel].NextRequest = NULL; AHI_Play(iounit->AudioCtrl, AHIP_BeginChannel, channel, AHIP_LoopFreq, ioreq->ahir_Frequency, AHIP_LoopVol, ioreq->ahir_Volume, AHIP_LoopPan, ioreq->ahir_Position, AHIP_LoopSound, GetExtras(ioreq)->Sound, AHIP_LoopOffset, ioreq->ahir_Std.io_Actual, AHIP_LoopLength, ioreq->ahir_Std.io_Length - ioreq->ahir_Std.io_Actual, AHIP_EndChannel, NULL, TAG_DONE); AHIsub_Enable((struct AHIAudioCtrlDrv *) iounit->AudioCtrl); } } } else // She tried to add more than one request to another one { ioreq->ahir_Std.io_Error = AHIE_UNKNOWN; TermIO(ioreq, AHIBase); } } else // Sound is not delayed { ioreq->ahir_Link=NULL; AddWriter(ioreq, iounit, AHIBase); } ReleaseSemaphore(&iounit->ListLock); } else // No free sound found, or sound failed to load { ioreq->ahir_Std.io_Error = AHIE_UNKNOWN; TermIO(ioreq, AHIBase); } }