comparison ALmixer.c @ 29:1c23805d5ce9

Optimization to destroy bookkeeping thread on BeginInterruption() and recreate it on EndInterruption(). I'm concerned that Android may be running this thread and eating up unnecessary sleep cycles, particularly on certain devices that may have pathological sleep disorders. (There is a report about Samsung Galaxy Tab.)
author Eric Wing <ewing . public |-at-| gmail . com>
date Mon, 28 Mar 2011 16:05:25 -0700
parents 60500a33735a
children a554e41eeb13
comparison
equal deleted inserted replaced
28:60500a33735a 29:1c23805d5ce9
221 221
222 #ifdef ENABLE_ALMIXER_THREADS 222 #ifdef ENABLE_ALMIXER_THREADS
223 /* This is for a simple lock system. It is not meant to be good, 223 /* This is for a simple lock system. It is not meant to be good,
224 * but just sufficient to minimize/avoid threading issues 224 * but just sufficient to minimize/avoid threading issues
225 */ 225 */
226 static ALuint g_StreamThreadEnabled = 0;
226 static SDL_mutex* s_simpleLock; 227 static SDL_mutex* s_simpleLock;
227 static SDL_Thread* Stream_Thread_global = NULL; 228 static SDL_Thread* Stream_Thread_global = NULL;
228 #endif /* ENABLE_ALMIXER_THREADS */ 229 #endif /* ENABLE_ALMIXER_THREADS */
229 230
230 static LinkedList* s_listOfALmixerData = NULL; 231 static LinkedList* s_listOfALmixerData = NULL;
231 232
232 /* Special stuff for iOS interruption handling */ 233 /* Special stuff for iOS interruption handling */
234 ALuint g_inInterruption = 0;
233 static ALCcontext* s_interruptionContext = NULL; 235 static ALCcontext* s_interruptionContext = NULL;
234 236
235 237
236 #ifdef __APPLE__ 238 #ifdef __APPLE__
237 static ALvoid Internal_alcMacOSXMixerOutputRate(const ALdouble sample_rate) 239 static ALvoid Internal_alcMacOSXMixerOutputRate(const ALdouble sample_rate)
6190 6192
6191 static int Stream_Data_Thread_Callback(void* data) 6193 static int Stream_Data_Thread_Callback(void* data)
6192 { 6194 {
6193 ALint retval; 6195 ALint retval;
6194 6196
6195 while(ALmixer_Initialized) 6197 while(g_StreamThreadEnabled)
6196 { 6198 {
6197 retval = Update_ALmixer(data); 6199 retval = Update_ALmixer(data);
6198 /* 0 means that nothing needed updating and 6200 /* 0 means that nothing needed updating and
6199 * the function returned quickly 6201 * the function returned quickly
6200 */ 6202 */
6771 ALmixer_Initialized = 0; 6773 ALmixer_Initialized = 0;
6772 Number_of_Channels_global = 0; 6774 Number_of_Channels_global = 0;
6773 return AL_FALSE; 6775 return AL_FALSE;
6774 } 6776 }
6775 6777
6776 6778 g_StreamThreadEnabled = 1;
6777 Stream_Thread_global = SDL_CreateThread(Stream_Data_Thread_Callback, NULL); 6779 Stream_Thread_global = SDL_CreateThread(Stream_Data_Thread_Callback, NULL);
6778 if(NULL == Stream_Thread_global) 6780 if(NULL == Stream_Thread_global)
6779 { 6781 {
6780 /* SDL sets the error message already? */ 6782 /* SDL sets the error message already? */
6781 SDL_DestroyMutex(s_simpleLock); 6783 SDL_DestroyMutex(s_simpleLock);
6785 LinkedList_Free(s_listOfALmixerData); 6787 LinkedList_Free(s_listOfALmixerData);
6786 alcDestroyContext(context); 6788 alcDestroyContext(context);
6787 alcCloseDevice(dev); 6789 alcCloseDevice(dev);
6788 ALmixer_Initialized = 0; 6790 ALmixer_Initialized = 0;
6789 Number_of_Channels_global = 0; 6791 Number_of_Channels_global = 0;
6792 g_StreamThreadEnabled = 0;
6790 return AL_FALSE; 6793 return AL_FALSE;
6791 } 6794 }
6792 6795
6793 /* Note: Only a few platforms change the priority. See implementation for notes. */ 6796 /* Note: Only a few platforms change the priority. See implementation for notes. */
6794 Internal_LowerThreadPriority(Stream_Thread_global); 6797 Internal_LowerThreadPriority(Stream_Thread_global);
7328 Number_of_Channels_global = 0; 7331 Number_of_Channels_global = 0;
7329 return AL_FALSE; 7332 return AL_FALSE;
7330 } 7333 }
7331 7334
7332 7335
7336 g_StreamThreadEnabled = 1;
7333 Stream_Thread_global = SDL_CreateThread(Stream_Data_Thread_Callback, NULL); 7337 Stream_Thread_global = SDL_CreateThread(Stream_Data_Thread_Callback, NULL);
7334 if(NULL == Stream_Thread_global) 7338 if(NULL == Stream_Thread_global)
7335 { 7339 {
7336 /* SDL sets the error message already? */ 7340 /* SDL sets the error message already? */
7337 SDL_DestroyMutex(s_simpleLock); 7341 SDL_DestroyMutex(s_simpleLock);
7338 free(source); 7342 free(source);
7339 free(ALmixer_Channel_List); 7343 free(ALmixer_Channel_List);
7340 free(Source_Map_List); 7344 free(Source_Map_List);
7341 ALmixer_Initialized = 0; 7345 ALmixer_Initialized = 0;
7342 Number_of_Channels_global = 0; 7346 Number_of_Channels_global = 0;
7347 g_StreamThreadEnabled = 0;
7343 return AL_FALSE; 7348 return AL_FALSE;
7344 } 7349 }
7345 7350
7346 /* Note: Only a few platforms change the priority. See implementation for notes. */ 7351 /* Note: Only a few platforms change the priority. See implementation for notes. */
7347 Internal_LowerThreadPriority(Stream_Thread_global); 7352 Internal_LowerThreadPriority(Stream_Thread_global);
7358 return AL_TRUE; 7363 return AL_TRUE;
7359 } 7364 }
7360 7365
7361 void ALmixer_BeginInterruption() 7366 void ALmixer_BeginInterruption()
7362 { 7367 {
7363 #ifdef ENABLE_ALMIXER_THREADS 7368 if(1 == g_inInterruption)
7364 SDL_LockMutex(s_simpleLock); 7369 {
7370 return;
7371 }
7372 #ifdef ENABLE_ALMIXER_THREADS
7373 /* Kill bookkeeping thread to help minimize wasted CPU resources */
7374
7375 /* Is locking really necessary here? */
7376 /* SDL_LockMutex(s_simpleLock); */
7377 g_StreamThreadEnabled = 0;
7378 /* SDL_UnlockMutex(s_simpleLock); */
7379
7380 SDL_WaitThread(Stream_Thread_global, NULL);
7381 Stream_Thread_global = NULL;
7382
7365 #endif 7383 #endif
7366 s_interruptionContext = alcGetCurrentContext(); 7384 s_interruptionContext = alcGetCurrentContext();
7367 if(NULL != s_interruptionContext) 7385 if(NULL != s_interruptionContext)
7368 { 7386 {
7369 /* iOS alcSuspendContext is a no-op */ 7387 /* iOS alcSuspendContext is a no-op */
7370 alcSuspendContext(s_interruptionContext); 7388 alcSuspendContext(s_interruptionContext);
7371 alcMakeContextCurrent(NULL); 7389 alcMakeContextCurrent(NULL);
7372 } 7390 }
7373 #ifdef ENABLE_ALMIXER_THREADS 7391
7374 SDL_UnlockMutex(s_simpleLock); 7392 g_inInterruption = 1;
7375 #endif
7376 } 7393 }
7377 7394
7378 void ALmixer_EndInterruption() 7395 void ALmixer_EndInterruption()
7379 { 7396 {
7380 #ifdef ENABLE_ALMIXER_THREADS 7397 if(0 == g_inInterruption)
7381 SDL_LockMutex(s_simpleLock); 7398 {
7382 #endif 7399 return;
7400 }
7383 7401
7384 /* Note: iOS, you need to set the AudioSession active. 7402 /* Note: iOS, you need to set the AudioSession active.
7385 * But if the AudioSession is not initialized, this SetActive 7403 * But if the AudioSession is not initialized, this SetActive
7386 * call fails. 7404 * call fails.
7387 * So this is probably better if calling app sets this. 7405 * So this is probably better if calling app sets this.
7401 alcMakeContextCurrent(s_interruptionContext); 7419 alcMakeContextCurrent(s_interruptionContext);
7402 alcProcessContext(s_interruptionContext); 7420 alcProcessContext(s_interruptionContext);
7403 s_interruptionContext = NULL; 7421 s_interruptionContext = NULL;
7404 } 7422 }
7405 #ifdef ENABLE_ALMIXER_THREADS 7423 #ifdef ENABLE_ALMIXER_THREADS
7406 SDL_UnlockMutex(s_simpleLock); 7424 g_StreamThreadEnabled = 1;
7407 #endif 7425
7426 Stream_Thread_global = SDL_CreateThread(Stream_Data_Thread_Callback, NULL);
7427 if(NULL == Stream_Thread_global)
7428 {
7429 fprintf(stderr, "Critical Error: Could not create bookkeeping thread in EndInterruption\n");
7430 }
7431 #endif
7432 g_inInterruption = 0;
7408 } 7433 }
7409 7434
7410 /* Keep the return value void to allow easy use with 7435 /* Keep the return value void to allow easy use with
7411 * atexit() 7436 * atexit()
7412 */ 7437 */
7418 7443
7419 if( ! ALmixer_Initialized) 7444 if( ! ALmixer_Initialized)
7420 { 7445 {
7421 return; 7446 return;
7422 } 7447 }
7448
7423 #ifdef ENABLE_ALMIXER_THREADS 7449 #ifdef ENABLE_ALMIXER_THREADS
7424 SDL_LockMutex(s_simpleLock); 7450 SDL_LockMutex(s_simpleLock);
7425 #endif 7451 #endif
7426 7452
7427 /* Several things we need to do: 7453 /* Several things we need to do:
7455 Internal_HaltChannel(-1, AL_FALSE); 7481 Internal_HaltChannel(-1, AL_FALSE);
7456 7482
7457 /* This flag will cause the thread to terminate */ 7483 /* This flag will cause the thread to terminate */
7458 ALmixer_Initialized = 0; 7484 ALmixer_Initialized = 0;
7459 #ifdef ENABLE_ALMIXER_THREADS 7485 #ifdef ENABLE_ALMIXER_THREADS
7486 g_StreamThreadEnabled = 0;
7460 SDL_UnlockMutex(s_simpleLock); 7487 SDL_UnlockMutex(s_simpleLock);
7488 /* This is safe to call with NULL thread, so we don't need to do anything special for interruptions. */
7461 SDL_WaitThread(Stream_Thread_global, NULL); 7489 SDL_WaitThread(Stream_Thread_global, NULL);
7490 Stream_Thread_global = NULL;
7491 g_inInterruption = 0;
7462 7492
7463 SDL_DestroyMutex(s_simpleLock); 7493 SDL_DestroyMutex(s_simpleLock);
7464 #endif 7494 #endif
7465 7495
7466 /* Delete all the OpenAL sources */ 7496 /* Delete all the OpenAL sources */