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.
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
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index 4c43693..ec3817b 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);
}