From 7d2108ce819c82e516199994302b6e3814f02af4 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 7 Oct 2016 19:39:43 -0400 Subject: [PATCH] audio: Backed out the audio-thread detaching changes. It added a ton of complexity. A simpler solution might arise at some point though. --- src/audio/SDL_audio.c | 107 ++++++++---------------------------------- 1 file changed, 19 insertions(+), 88 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 08b801ed8..460852d7f 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -708,38 +708,6 @@ SDL_ClearQueuedAudio(SDL_AudioDeviceID devid) free_audio_queue(packet); } -void -SDL_FinalizeAudioDevice(SDL_AudioDevice *device) -{ - if (!device) { - return; - } - - SDL_AtomicSet(&device->shutdown, 1); /* just in case. */ - SDL_AtomicSet(&device->enabled, 0); - - /* lock/unlock here so we don't race if the audio thread saw the shutdown - var without locking, and the thread that requested shutdown is now - trying to unlock the mutex while we destroy it. Threading is hard. */ - current_audio.impl.LockDevice(device); - current_audio.impl.UnlockDevice(device); - - if (device->mixer_lock != NULL) { - SDL_DestroyMutex(device->mixer_lock); - } - SDL_free(device->fake_stream); - if (device->convert.needed) { - SDL_free(device->convert.buf); - } - if (device->hidden != NULL) { - current_audio.impl.CloseDevice(device); - } - - free_audio_queue(device->buffer_queue_head); - free_audio_queue(device->buffer_queue_pool); - - SDL_free(device); -} /* The general mixing thread function */ static int SDLCALL @@ -819,8 +787,6 @@ SDL_RunAudio(void *devicep) /* Wait for the audio to drain. */ SDL_Delay(((device->spec.samples * 1000) / device->spec.freq) * 2); - SDL_FinalizeAudioDevice(device); - return 0; } @@ -902,8 +868,6 @@ SDL_CaptureAudio(void *devicep) current_audio.impl.FlushCapture(device); - SDL_FinalizeAudioDevice(device); - return 0; } @@ -1118,19 +1082,6 @@ close_audio_device(SDL_AudioDevice * device) return; } - /* It's possible the audio device can hang at the OS level for - several reasons (buggy drivers, etc), so if we've got a thread in - flight, we mark the device as ready to shutdown and return - immediately. The thread will either notice this and clean everything - up when it can, or it's frozen and helpless, but since we've already - detached the thread, it's none of our concern. Otherwise, we might - hang too. */ - - /* Note this can still hang if we initialized the device but failed - to finish setting up, forcing _this_ thread to do the cleanup, but - oh well. */ - - /* take it out of our open list now, though, even if device hangs. */ if (device->id > 0) { SDL_AudioDevice *opendev = open_devices[device->id - 1]; SDL_assert((opendev == device) || (opendev == NULL)); @@ -1139,43 +1090,26 @@ close_audio_device(SDL_AudioDevice * device) } } - if (!current_audio.impl.ProvidesOwnCallbackThread && !device->thread) { - /* no thread...maybe we're cleaning up a half-opened failure. */ - SDL_FinalizeAudioDevice(device); /* do it ourselves. */ - } else if (current_audio.impl.ProvidesOwnCallbackThread) { - /* !!! FIXME: this is sort of a mess, because we _should_ treat this - !!! FIXME: the same as our internal threads, but those targets - !!! FIXME: need refactoring first: they need to call - !!! FIXME: SDL_FinalizeAudioDevice() themselves and also have - !!! FIXME: their CloseDevice() code deal with cleaning up - !!! FIXME: half-initialized opens _and_ normal runs. So for now, - !!! FIXME: nothing to do here but pray this doesn't hang. - !!! FIXME: (the TODO list: coreaudio, emscripten, nacl, haiku) */ - SDL_FinalizeAudioDevice(device); - } else { - Uint32 delay = 0; - - if (!device->iscapture) { - const SDL_AudioSpec *spec = &device->spec; - delay = ((spec->samples * 1000) / spec->freq) * 2; - } - - /* Lock to make sure an audio callback doesn't fire after we return. - Presumably, if a device hangs, it'll not be holding this mutex, - since it should only be held during the app's audio callback. */ - current_audio.impl.LockDevice(device); - SDL_AtomicSet(&device->shutdown, 1); /* let the thread do it. */ - SDL_AtomicSet(&device->enabled, 0); - current_audio.impl.UnlockDevice(device); - - /* device is no longer safe to touch at this point. */ - - if (delay > 0) { - /* Block the amount that is roughly pending for playback, so we - don't drop audio if the process exits right after this call. */ - SDL_Delay(delay); - } + SDL_AtomicSet(&device->shutdown, 1); + SDL_AtomicSet(&device->enabled, 0); + if (device->thread != NULL) { + SDL_WaitThread(device->thread, NULL); } + if (device->mixer_lock != NULL) { + SDL_DestroyMutex(device->mixer_lock); + } + SDL_free(device->fake_stream); + if (device->convert.needed) { + SDL_free(device->convert.buf); + } + if (device->hidden != NULL) { + current_audio.impl.CloseDevice(device); + } + + free_audio_queue(device->buffer_queue_head); + free_audio_queue(device->buffer_queue_pool); + + SDL_free(device); } @@ -1494,9 +1428,6 @@ open_audio_device(const char *devname, int iscapture, SDL_SetError("Couldn't create audio thread"); return 0; } - - /* don't ever join on this thread; it will clean itself up. */ - SDL_DetachThread(device->thread); } return device->id;