From e7347a4027b8d3e156ec367cb9623571a3066b0e Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 6 Aug 2016 02:27:55 -0400 Subject: [PATCH] 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. --- src/audio/SDL_audio.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 4c43693427167..ec3817bb487d7 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -586,20 +586,44 @@ void SDL_ClearQueuedAudio(SDL_AudioDeviceID devid) { SDL_AudioDevice *device = get_audio_device(devid); - SDL_AudioBufferQueue *buffer = NULL; + SDL_AudioBufferQueue *packet; + if (!device) { return; /* nothing to do. */ } /* Blank out the device and release the mutex. Free it afterwards. */ 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_head = NULL; 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); - free_audio_queue(buffer); + /* free any extra packets we didn't keep in the pool. */ + free_audio_queue(packet); }