audio: Backed out the audio-thread detaching changes. It added a ton of complexity. A simpler solution might arise at some point though.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index 08b801e..460852d 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);
+ 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);
+ }
- /* device is no longer safe to touch at this point. */
+ free_audio_queue(device->buffer_queue_head);
+ free_audio_queue(device->buffer_queue_pool);
- 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_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;