ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

thread.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.