audio: SDL_ClearQueuedAudio() should free everything but two packets.

Otherwise, if you had a massive, one-time queue buildup, the memory from that
remains allocated until you close the device. Also, if you are just using a
reasonable amount of space, this would previously cause you to reallocate it
over and over instead of keeping a little bit of memory around.
This commit is contained in:
Ryan C. Gordon 2016-08-06 02:27:55 -04:00
parent 9a33154450
commit e7347a4027

View File

@ -586,20 +586,44 @@ void
SDL_ClearQueuedAudio(SDL_AudioDeviceID devid) SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
{ {
SDL_AudioDevice *device = get_audio_device(devid); SDL_AudioDevice *device = get_audio_device(devid);
SDL_AudioBufferQueue *buffer = NULL; SDL_AudioBufferQueue *packet;
if (!device) { if (!device) {
return; /* nothing to do. */ return; /* nothing to do. */
} }
/* Blank out the device and release the mutex. Free it afterwards. */ /* Blank out the device and release the mutex. Free it afterwards. */
current_audio.impl.LockDevice(device); current_audio.impl.LockDevice(device);
buffer = device->buffer_queue_head;
/* merge the available pool and the current queue into one list. */
packet = device->buffer_queue_head;
if (packet) {
device->buffer_queue_tail->next = device->buffer_queue_pool;
} else {
packet = device->buffer_queue_pool;
}
/* Remove the queued packets from the device. */
device->buffer_queue_tail = NULL; device->buffer_queue_tail = NULL;
device->buffer_queue_head = NULL; device->buffer_queue_head = NULL;
device->queued_bytes = 0; device->queued_bytes = 0;
device->buffer_queue_pool = packet;
/* Keep up to two packets in the pool to reduce future malloc pressure. */
if (packet) {
if (!packet->next) {
packet = NULL; /* one packet (the only one) for the pool. */
} else {
SDL_AudioBufferQueue *next = packet->next->next;
packet->next->next = NULL; /* two packets for the pool. */
packet = next; /* rest will be freed. */
}
}
current_audio.impl.UnlockDevice(device); current_audio.impl.UnlockDevice(device);
free_audio_queue(buffer); /* free any extra packets we didn't keep in the pool. */
free_audio_queue(packet);
} }