changeset 37:b346b6608eab

Fixed memory leak in Quit due to changes related to background thread removal. FreeData was quick escaping because it checked for ALmixer_Initialized which is now false by the time the code is reached. Code was refactored to introduce an Internal_FreeData which skips this check. Also, I think there is another 'bug' where I should actually be able to delete buffers even though the context is NULL as long as there is a device. But this is all really ugly corner case stuff.
author Eric Wing <ewing@anscamobile.com>
date Mon, 11 Apr 2011 17:19:24 -0700
parents b65ad8b6ccf3
children 71b465ff0622 e10dd3056782
files ALmixer.c
diffstat 1 files changed, 63 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/ALmixer.c	Thu Apr 07 19:19:07 2011 -0700
+++ b/ALmixer.c	Mon Apr 11 17:19:24 2011 -0700
@@ -4773,6 +4773,65 @@
 
 
 
+static void Internal_FreeData(ALmixer_Data* data)
+{
+	ALenum error;
+	if(NULL == data)
+	{
+		return;
+	}
+	
+	if(data->decoded_all)
+	{
+		/* If access_data was enabled, then the Sound_Sample*
+		 * still exists. We need to free it
+		 */
+		if(data->sample != NULL)
+		{
+			Sound_FreeSample(data->sample);
+		}
+		alDeleteBuffers(1, data->buffer);
+		if((error = alGetError()) != AL_NO_ERROR)
+		{
+			fprintf(stderr, "ALmixer_FreeData: alDeleteBuffers failed. %s\n", alGetString(error));				
+		}
+	}
+	else
+	{
+		ALuint i;
+		
+		/* Delete buffer copies if access_data was enabled */
+		if(data->buffer_map_list != NULL)
+		{
+			for(i=0; i<data->max_queue_buffers; i++)
+			{
+				free(data->buffer_map_list[i].data);
+			}
+			free(data->buffer_map_list);
+		}
+		if(data->circular_buffer_queue != NULL)
+		{
+			CircularQueueUnsignedInt_FreeQueue(data->circular_buffer_queue);
+		}
+			
+		Sound_FreeSample(data->sample);
+		alDeleteBuffers(data->max_queue_buffers, data->buffer);		
+		if((error = alGetError()) != AL_NO_ERROR)
+		{
+			fprintf(stderr, "ALmixer_FreeData: alDeleteBuffers failed. %s\n", alGetString(error));				
+		}
+	}
+	free(data->buffer);
+
+	LinkedList_Remove(s_listOfALmixerData,
+		LinkedList_Find(s_listOfALmixerData, data, NULL)
+	);
+
+	free(data);
+}
+
+
+
 
 
 				
@@ -7517,7 +7576,8 @@
 	{
 		/* Note that ALmixer_FreeData will remove the data from the linked list for us so don't pop the list here. */
 		ALmixer_Data* almixer_data = LinkedList_PopBack(s_listOfALmixerData);
-		ALmixer_FreeData(almixer_data);
+		/* Watch out: ALmixer_FreeData used to escape because ALmixer_Initialized is now false. */
+		Internal_FreeData(almixer_data);
 	}
 	LinkedList_Free(s_listOfALmixerData);
 	s_listOfALmixerData = NULL;
@@ -8540,75 +8600,22 @@
 }
 
 
-
-
 void ALmixer_FreeData(ALmixer_Data* data)
 {
-	ALenum error;
-	if(NULL == data)
-	{
-		return;
-	}
-
 	if(AL_FALSE == ALmixer_Initialized)
 	{
 		return;
 	}
 
 	/* Bypass if in interruption event */
+	/* FIXME: Buffers are connected to devices, sources are connected to contexts. I should still be able to delete the buffers even if there is no context. */
 	if(NULL == alcGetCurrentContext())
 	{
 		fprintf(stderr, "ALmixer_FreeData: Programmer Error. You cannot delete data when the OpenAL content is currently NULL. You may have already called ALmixer_Quit() or are in an interruption event\n");
 		return;
 	}
 	
-	if(data->decoded_all)
-	{
-		/* If access_data was enabled, then the Sound_Sample*
-		 * still exists. We need to free it
-		 */
-		if(data->sample != NULL)
-		{
-			Sound_FreeSample(data->sample);
-		}
-		alDeleteBuffers(1, data->buffer);
-		if((error = alGetError()) != AL_NO_ERROR)
-		{
-			fprintf(stderr, "ALmixer_FreeData: alDeleteBuffers failed. %s\n", alGetString(error));				
-		}
-	}
-	else
-	{
-		ALuint i;
-		
-		/* Delete buffer copies if access_data was enabled */
-		if(data->buffer_map_list != NULL)
-		{
-			for(i=0; i<data->max_queue_buffers; i++)
-			{
-				free(data->buffer_map_list[i].data);
-			}
-			free(data->buffer_map_list);
-		}
-		if(data->circular_buffer_queue != NULL)
-		{
-			CircularQueueUnsignedInt_FreeQueue(data->circular_buffer_queue);
-		}
-			
-		Sound_FreeSample(data->sample);
-		alDeleteBuffers(data->max_queue_buffers, data->buffer);		
-		if((error = alGetError()) != AL_NO_ERROR)
-		{
-			fprintf(stderr, "ALmixer_FreeData: alDeleteBuffers failed. %s\n", alGetString(error));				
-		}
-	}
-	free(data->buffer);
-
-	LinkedList_Remove(s_listOfALmixerData,
-		LinkedList_Find(s_listOfALmixerData, data, NULL)
-	);
-
-	free(data);
+	Internal_FreeData(data);
 }
 
 ALint ALmixer_GetTotalTime(ALmixer_Data* data)