diff ALmixer.c @ 13:54aa96ae8912

Added LinkedList class to project. ALmixer now saves ALmixer_Data instances in a private linked list so when Quit is called, this memory can be cleaned up. This is meant to deal with two problems. First, SDL_sound does something similar which means since I wrap SDL_sound structures, I may be left with dangling pointers if. Second is the obvious auto-cleanup when quiting which is convenient for resetting.
author Eric Wing <ewing . public |-at-| gmail . com>
date Sat, 06 Nov 2010 00:37:29 -0700
parents bfe90b4f3d87
children 038baa026db3
line wrap: on
line diff
--- a/ALmixer.c	Fri Nov 05 20:59:13 2010 -0700
+++ b/ALmixer.c	Sat Nov 06 00:37:29 2010 -0700
@@ -62,6 +62,12 @@
  */
 #include "CircularQueue.h"
 
+/* SDL_sound keeps a private linked list of sounds which get auto-deleted
+ * on Sound_Quit. This might actually create some leaks for me in certain
+ * usage patterns. To be safe, I should do the same.
+ */
+#include "LinkedList.h"
+
 #ifdef ENABLE_ALMIXER_THREADS
 /* Needed for the Mutex locks (and threads if enabled) */
 	#ifdef ALMIXER_COMPILE_WITHOUT_SDL
@@ -227,6 +233,9 @@
 static SDL_Thread* Stream_Thread_global = NULL;
 #endif
 
+static LinkedList* s_listOfALmixerData = NULL;
+
+
 
 #ifdef __APPLE__
 static ALvoid Internal_alcMacOSXMixerOutputRate(const ALdouble sample_rate)
@@ -6398,11 +6407,24 @@
 	Channel_Data_Callback = NULL;
 	Channel_Data_Callback_Userdata = NULL;
 
+	/* Allocate memory for linked list of ALmixerData. */
+	s_listOfALmixerData = LinkedList_Create();
+	if(NULL == s_listOfALmixerData)
+	{
+		ALmixer_SetError("Couldn't create linked list");
+		alcDestroyContext(context);
+		alcCloseDevice(dev);
+		ALmixer_Initialized = 0;
+		Number_of_Channels_global = 0;
+		return AL_FALSE;
+	}
+
 	/* Allocate memory for the list of channels */
 	ALmixer_Channel_List = (struct ALmixer_Channel*) malloc(Number_of_Channels_global * sizeof(struct ALmixer_Channel));
 	if(NULL == ALmixer_Channel_List)
 	{
 		ALmixer_SetError("Out of Memory for Channel List");
+		LinkedList_Free(s_listOfALmixerData);
 		alcDestroyContext(context);
 		alcCloseDevice(dev);
 		ALmixer_Initialized = 0;
@@ -6416,6 +6438,7 @@
 	{
 		ALmixer_SetError("Out of Memory for Source Map List");
 		free(ALmixer_Channel_List);
+		LinkedList_Free(s_listOfALmixerData);		
 		alcDestroyContext(context);
 		alcCloseDevice(dev);
 		ALmixer_Initialized = 0;
@@ -6430,6 +6453,7 @@
 		ALmixer_SetError("Out of Memory for sources");
 		free(Source_Map_List);
 		free(ALmixer_Channel_List);
+		LinkedList_Free(s_listOfALmixerData);		
 		alcDestroyContext(context);
 		alcCloseDevice(dev);
 		ALmixer_Initialized = 0;
@@ -6446,6 +6470,7 @@
 		ALmixer_SetError("Couldn't generate sources: %s\n", alGetString(error));
 		free(ALmixer_Channel_List);
 		free(Source_Map_List);
+		LinkedList_Free(s_listOfALmixerData);		
 		alcDestroyContext(context);
 		alcCloseDevice(dev);
 		ALmixer_Initialized = 0;
@@ -6486,6 +6511,9 @@
 	/*
 	ALmixer_OutputDecoders();
 */
+
+
+
 #ifdef ENABLE_ALMIXER_THREADS
 	s_simpleLock = SDL_CreateMutex();
 	if(NULL == s_simpleLock)
@@ -6494,6 +6522,7 @@
 		free(source);
 		free(ALmixer_Channel_List);
 		free(Source_Map_List);
+		LinkedList_Free(s_listOfALmixerData);		
 		alcDestroyContext(context);
 		alcCloseDevice(dev);
 		ALmixer_Initialized = 0;
@@ -6510,6 +6539,7 @@
 		free(source);
 		free(ALmixer_Channel_List);
 		free(Source_Map_List);
+		LinkedList_Free(s_listOfALmixerData);		
 		alcDestroyContext(context);
 		alcCloseDevice(dev);
 		ALmixer_Initialized = 0;
@@ -6948,11 +6978,23 @@
 	Channel_Data_Callback = NULL;
 	Channel_Data_Callback_Userdata = NULL;
 
+	/* Allocate memory for linked list of ALmixerData. */
+	s_listOfALmixerData = LinkedList_Create();
+	if(NULL == s_listOfALmixerData)
+	{
+		ALmixer_SetError("Couldn't create linked list");
+		ALmixer_Initialized = 0;
+		Number_of_Channels_global = 0;
+		return AL_FALSE;
+	}
+
+
 	/* Allocate memory for the list of channels */
 	ALmixer_Channel_List = (struct ALmixer_Channel*) malloc(Number_of_Channels_global * sizeof(struct ALmixer_Channel));
 	if(NULL == ALmixer_Channel_List)
 	{
 		ALmixer_SetError("Out of Memory for Channel List");
+		LinkedList_Free(s_listOfALmixerData);		
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
 		return AL_FALSE;
@@ -6964,6 +7006,7 @@
 	{
 		ALmixer_SetError("Out of Memory for Source Map List");
 		free(ALmixer_Channel_List);
+		LinkedList_Free(s_listOfALmixerData);		
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
 		return AL_FALSE;
@@ -6976,6 +7019,7 @@
 		ALmixer_SetError("Out of Memory for sources");
 		free(Source_Map_List);
 		free(ALmixer_Channel_List);
+		LinkedList_Free(s_listOfALmixerData);		
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
 		return AL_FALSE;
@@ -6990,6 +7034,7 @@
 		ALmixer_SetError("Couldn't generate sources: %s\n", alGetString(error));
 		free(ALmixer_Channel_List);
 		free(Source_Map_List);
+		LinkedList_Free(s_listOfALmixerData);
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
 		return AL_FALSE;
@@ -7121,6 +7166,17 @@
 	}
 	alcCloseDevice(dev);
 	
+	/* Delete the list of ALmixerData's before Sound_Quit deletes
+	 * its own underlying information and I potentially have dangling pointers.
+	 */
+	while(LinkedList_Size(s_listOfALmixerData) > 0)
+	{
+		ALmixer_Data* almixer_data = LinkedList_PopBack(s_listOfALmixerData);
+		ALmixer_FreeData(almixer_data);
+	}
+	LinkedList_Free(s_listOfALmixerData);
+	s_listOfALmixerData = NULL;
+
 	Sound_Quit();
 
 #ifdef ALMIXER_COMPILE_WITHOUT_SDL
@@ -7857,6 +7913,10 @@
 		return NULL;
 	}
 		
+	/* Add the ALmixerData to an internal linked list so we can delete it on 
+	 * quit and avoid messy dangling issues with Sound_Quit
+	 */
+	LinkedList_PushBack(s_listOfALmixerData, ret_data);
 	return ret_data;
 }
 
@@ -8139,6 +8199,11 @@
 	}
 	}
 	free(data->buffer);
+
+	LinkedList_Remove(s_listOfALmixerData,
+		LinkedList_Find(s_listOfALmixerData, data, NULL)
+	);
+
 	free(data);
 }