Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenthread.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Sound System "MME Buddy" Library 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: lib/drivers/sound/mmebuddy/thread.c 00005 * 00006 * PURPOSE: Multimedia thread management 00007 * 00008 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) 00009 */ 00010 00011 #include "precomp.h" 00012 00013 DWORD WINAPI 00014 SoundThreadMain( 00015 IN LPVOID lpParameter OPTIONAL) 00016 { 00017 PSOUND_THREAD Thread = (PSOUND_THREAD) lpParameter; 00018 00019 SND_TRACE(L"SoundThread running :)\n"); 00020 00021 /* Callers will wait for us to be ready */ 00022 Thread->Running = TRUE; 00023 SetEvent(Thread->Events.Ready); 00024 00025 while ( Thread->Running ) 00026 { 00027 DWORD WaitResult; 00028 00029 /* Wait for a request, or an I/O completion */ 00030 WaitResult = WaitForSingleObjectEx(Thread->Events.Request, INFINITE, TRUE); 00031 SND_TRACE(L"SoundThread - Came out of waiting\n"); 00032 00033 if ( WaitResult == WAIT_OBJECT_0 ) 00034 { 00035 SND_TRACE(L"SoundThread - Processing request\n"); 00036 00037 if ( Thread->Request.Handler ) 00038 { 00039 Thread->Request.Result = Thread->Request.Handler(Thread->Request.SoundDeviceInstance, 00040 Thread->Request.Parameter); 00041 } 00042 else 00043 { 00044 Thread->Request.Result = MMSYSERR_ERROR; 00045 } 00046 00047 /* Announce completion of the request */ 00048 SetEvent(Thread->Events.Done); 00049 /* Accept new requests */ 00050 SetEvent(Thread->Events.Ready); 00051 } 00052 else if ( WaitResult == WAIT_IO_COMPLETION ) 00053 { 00054 SND_TRACE(L"SoundThread - Processing IO completion\n"); 00055 /* TODO? What do we do here? Stream stuff? */ 00056 } 00057 else 00058 { 00059 /* This should not happen! */ 00060 SND_ASSERT(FALSE); 00061 } 00062 00063 } 00064 00065 SND_TRACE(L"Sound thread terminated\n"); 00066 00067 return 0; 00068 } 00069 00070 MMRESULT 00071 CallSoundThread( 00072 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 00073 IN SOUND_THREAD_REQUEST_HANDLER RequestHandler, 00074 IN PVOID Parameter OPTIONAL) 00075 { 00076 PSOUND_THREAD Thread; 00077 00078 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) ); 00079 VALIDATE_MMSYS_PARAMETER( RequestHandler ); 00080 00081 Thread = SoundDeviceInstance->Thread; 00082 00083 SND_TRACE(L"Waiting for READY event\n"); 00084 WaitForSingleObject(Thread->Events.Ready, INFINITE); 00085 00086 Thread->Request.Result = MMSYSERR_NOTSUPPORTED; 00087 Thread->Request.Handler = RequestHandler; 00088 Thread->Request.SoundDeviceInstance = SoundDeviceInstance; 00089 Thread->Request.Parameter = Parameter; 00090 00091 /* Notify the thread it has work to do */ 00092 SND_TRACE(L"Setting REQUEST event\n"); 00093 SetEvent(Thread->Events.Request); 00094 00095 /* Wait for the work to be done */ 00096 SND_TRACE(L"Waiting for DONE event\n"); 00097 WaitForSingleObject(Thread->Events.Done, INFINITE); 00098 00099 return Thread->Request.Result; 00100 } 00101 00102 00103 MMRESULT 00104 SoundThreadTerminator( 00105 IN PSOUND_DEVICE_INSTANCE Instance, 00106 IN PVOID Parameter) 00107 { 00108 PSOUND_THREAD Thread = (PSOUND_THREAD) Parameter; 00109 00110 SND_TRACE(L"Sound thread terminator routine called\n"); 00111 SND_ASSERT( Thread ); 00112 00113 Thread->Running = FALSE; 00114 00115 return MMSYSERR_NOERROR; 00116 } 00117 00118 MMRESULT 00119 TerminateSoundThread( 00120 IN PSOUND_THREAD Thread) 00121 { 00122 DWORD WaitResult; 00123 00124 SND_ASSERT( Thread ); 00125 00126 SND_TRACE(L"Waiting for READY event\n"); 00127 WaitForSingleObject(Thread->Events.Ready, INFINITE); 00128 00129 Thread->Request.Result = MMSYSERR_NOTSUPPORTED; 00130 Thread->Request.Handler = SoundThreadTerminator; 00131 Thread->Request.SoundDeviceInstance = NULL; 00132 Thread->Request.Parameter = (PVOID) Thread; 00133 00134 /* Notify the thread it has work to do */ 00135 SND_TRACE(L"Setting REQUEST event\n"); 00136 SetEvent(Thread->Events.Request); 00137 00138 /* Wait for the work to be done */ 00139 SND_TRACE(L"Waiting for DONE event\n"); 00140 WaitForSingleObject(Thread->Events.Done, INFINITE); 00141 00142 /* Wait for the thread to actually end */ 00143 WaitResult = WaitForSingleObject(Thread->Handle, INFINITE); 00144 SND_ASSERT( WaitResult == WAIT_OBJECT_0 ); 00145 00146 /* Close the thread and invalidate the handle */ 00147 CloseHandle(Thread->Handle); /* Is this needed? */ 00148 Thread->Handle = INVALID_HANDLE_VALUE; 00149 00150 return MMSYSERR_NOERROR; 00151 } 00152 00153 00154 MMRESULT 00155 CreateSoundThreadEvents( 00156 OUT HANDLE* ReadyEvent, 00157 OUT HANDLE* RequestEvent, 00158 OUT HANDLE* DoneEvent) 00159 { 00160 BOOL ok; 00161 00162 VALIDATE_MMSYS_PARAMETER( ReadyEvent ); 00163 VALIDATE_MMSYS_PARAMETER( RequestEvent ); 00164 VALIDATE_MMSYS_PARAMETER( DoneEvent ); 00165 00166 SND_TRACE(L"Creating thread events\n"); 00167 00168 /* Initialise these so we can identify them upon failure */ 00169 *ReadyEvent = *RequestEvent = *DoneEvent = INVALID_HANDLE_VALUE; 00170 00171 ok = (*ReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) != INVALID_HANDLE_VALUE; 00172 ok &= (*RequestEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) != INVALID_HANDLE_VALUE; 00173 ok &= (*DoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) != INVALID_HANDLE_VALUE; 00174 00175 /* If something went wrong, clean up */ 00176 if ( ! ok ) 00177 { 00178 if ( *ReadyEvent != INVALID_HANDLE_VALUE ) 00179 CloseHandle(*ReadyEvent); 00180 00181 if ( *RequestEvent != INVALID_HANDLE_VALUE ) 00182 CloseHandle(*RequestEvent); 00183 00184 if ( *DoneEvent != INVALID_HANDLE_VALUE ) 00185 CloseHandle(*DoneEvent); 00186 00187 return MMSYSERR_NOMEM; 00188 } 00189 00190 return MMSYSERR_NOERROR; 00191 } 00192 00193 MMRESULT 00194 DestroySoundThreadEvents( 00195 IN HANDLE ReadyEvent, 00196 IN HANDLE RequestEvent, 00197 IN HANDLE DoneEvent) 00198 { 00199 VALIDATE_MMSYS_PARAMETER( ReadyEvent != INVALID_HANDLE_VALUE ); 00200 VALIDATE_MMSYS_PARAMETER( RequestEvent != INVALID_HANDLE_VALUE ); 00201 VALIDATE_MMSYS_PARAMETER( DoneEvent != INVALID_HANDLE_VALUE ); 00202 00203 SND_TRACE(L"Destroying thread events\n"); 00204 00205 CloseHandle(ReadyEvent); 00206 CloseHandle(RequestEvent); 00207 CloseHandle(DoneEvent); 00208 00209 return MMSYSERR_NOERROR; 00210 } 00211 00212 MMRESULT 00213 CreateSoundThread( 00214 OUT PSOUND_THREAD* Thread) 00215 { 00216 MMRESULT Result; 00217 PSOUND_THREAD NewThread; 00218 00219 VALIDATE_MMSYS_PARAMETER( Thread ); 00220 00221 NewThread = AllocateStruct(SOUND_THREAD); 00222 if ( ! NewThread ) 00223 return MMSYSERR_NOMEM; 00224 00225 /* Prepare the events we'll be using to sync. everything */ 00226 Result = CreateSoundThreadEvents(&NewThread->Events.Ready, 00227 &NewThread->Events.Request, 00228 &NewThread->Events.Done); 00229 00230 if ( ! MMSUCCESS(Result) ) 00231 { 00232 FreeMemory(NewThread); 00233 return TranslateInternalMmResult(Result); 00234 } 00235 00236 SND_TRACE(L"Creating a sound thread\n"); 00237 NewThread->Handle = CreateThread(NULL, 00238 0, 00239 &SoundThreadMain, 00240 (LPVOID) NewThread, 00241 CREATE_SUSPENDED, 00242 NULL); 00243 00244 /* Something went wrong, bail out! */ 00245 if ( NewThread->Handle == INVALID_HANDLE_VALUE ) 00246 { 00247 SND_ERR(L"Sound thread creation failed!\n"); 00248 DestroySoundThreadEvents(NewThread->Events.Ready, 00249 NewThread->Events.Request, 00250 NewThread->Events.Done); 00251 00252 FreeMemory(NewThread); 00253 00254 return Win32ErrorToMmResult(GetLastError()); 00255 } 00256 00257 /* Wake the thread up */ 00258 if ( ResumeThread(NewThread->Handle) == -1 ) 00259 { 00260 SND_ERR(L"Failed to resume thread!\n"); 00261 CloseHandle(NewThread->Handle); 00262 DestroySoundThreadEvents(NewThread->Events.Ready, 00263 NewThread->Events.Request, 00264 NewThread->Events.Done); 00265 00266 FreeMemory(NewThread); 00267 return Win32ErrorToMmResult(GetLastError()); 00268 } 00269 00270 /* If all is well we can now give the thread to the caller */ 00271 *Thread = NewThread; 00272 return MMSYSERR_NOERROR; 00273 } 00274 00275 MMRESULT 00276 DestroySoundThread( 00277 IN PSOUND_THREAD Thread) 00278 { 00279 VALIDATE_MMSYS_PARAMETER( Thread ); 00280 SND_ASSERT( Thread->Handle != INVALID_HANDLE_VALUE ); 00281 00282 SND_TRACE(L"Terminating sound thread\n"); 00283 00284 /* Tell the thread to terminate itself */ 00285 TerminateSoundThread(Thread); 00286 00287 SND_TRACE(L"Sound thread terminated, performing cleanup of thread resources\n"); 00288 00289 CloseHandle(Thread->Handle); /* Is this needed? */ 00290 Thread->Handle = INVALID_HANDLE_VALUE; 00291 00292 DestroySoundThreadEvents(Thread->Events.Ready, 00293 Thread->Events.Request, 00294 Thread->Events.Done); 00295 00296 /* Wipe and free the memory used for the thread */ 00297 ZeroMemory(Thread, sizeof(SOUND_THREAD)); 00298 FreeMemory(Thread); 00299 00300 SND_TRACE(L"Finished thread cleanup\n"); 00301 00302 return MMSYSERR_NOERROR; 00303 } 00304 Generated on Sun May 27 2012 04:24:31 for ReactOS by
1.7.6.1
|