Mercurial > almixer_isolated
comparison ALmixer.c @ 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 | 2b0b55b7f8cf |
comparison
equal
deleted
inserted
replaced
36:b65ad8b6ccf3 | 37:b346b6608eab |
---|---|
4767 ALmixer_SetError("Cannot query source: %s", ALmixer_GetError()); | 4767 ALmixer_SetError("Cannot query source: %s", ALmixer_GetError()); |
4768 return -1; | 4768 return -1; |
4769 } | 4769 } |
4770 | 4770 |
4771 return Internal_PausedChannel(channel); | 4771 return Internal_PausedChannel(channel); |
4772 } | |
4773 | |
4774 | |
4775 | |
4776 static void Internal_FreeData(ALmixer_Data* data) | |
4777 { | |
4778 ALenum error; | |
4779 if(NULL == data) | |
4780 { | |
4781 return; | |
4782 } | |
4783 | |
4784 if(data->decoded_all) | |
4785 { | |
4786 /* If access_data was enabled, then the Sound_Sample* | |
4787 * still exists. We need to free it | |
4788 */ | |
4789 if(data->sample != NULL) | |
4790 { | |
4791 Sound_FreeSample(data->sample); | |
4792 } | |
4793 alDeleteBuffers(1, data->buffer); | |
4794 if((error = alGetError()) != AL_NO_ERROR) | |
4795 { | |
4796 fprintf(stderr, "ALmixer_FreeData: alDeleteBuffers failed. %s\n", alGetString(error)); | |
4797 } | |
4798 } | |
4799 else | |
4800 { | |
4801 ALuint i; | |
4802 | |
4803 /* Delete buffer copies if access_data was enabled */ | |
4804 if(data->buffer_map_list != NULL) | |
4805 { | |
4806 for(i=0; i<data->max_queue_buffers; i++) | |
4807 { | |
4808 free(data->buffer_map_list[i].data); | |
4809 } | |
4810 free(data->buffer_map_list); | |
4811 } | |
4812 if(data->circular_buffer_queue != NULL) | |
4813 { | |
4814 CircularQueueUnsignedInt_FreeQueue(data->circular_buffer_queue); | |
4815 } | |
4816 | |
4817 Sound_FreeSample(data->sample); | |
4818 alDeleteBuffers(data->max_queue_buffers, data->buffer); | |
4819 if((error = alGetError()) != AL_NO_ERROR) | |
4820 { | |
4821 fprintf(stderr, "ALmixer_FreeData: alDeleteBuffers failed. %s\n", alGetString(error)); | |
4822 } | |
4823 } | |
4824 free(data->buffer); | |
4825 | |
4826 LinkedList_Remove(s_listOfALmixerData, | |
4827 LinkedList_Find(s_listOfALmixerData, data, NULL) | |
4828 ); | |
4829 | |
4830 free(data); | |
4772 } | 4831 } |
4773 | 4832 |
4774 | 4833 |
4775 | 4834 |
4776 | 4835 |
7515 */ | 7574 */ |
7516 while(LinkedList_Size(s_listOfALmixerData) > 0) | 7575 while(LinkedList_Size(s_listOfALmixerData) > 0) |
7517 { | 7576 { |
7518 /* Note that ALmixer_FreeData will remove the data from the linked list for us so don't pop the list here. */ | 7577 /* Note that ALmixer_FreeData will remove the data from the linked list for us so don't pop the list here. */ |
7519 ALmixer_Data* almixer_data = LinkedList_PopBack(s_listOfALmixerData); | 7578 ALmixer_Data* almixer_data = LinkedList_PopBack(s_listOfALmixerData); |
7520 ALmixer_FreeData(almixer_data); | 7579 /* Watch out: ALmixer_FreeData used to escape because ALmixer_Initialized is now false. */ |
7580 Internal_FreeData(almixer_data); | |
7521 } | 7581 } |
7522 LinkedList_Free(s_listOfALmixerData); | 7582 LinkedList_Free(s_listOfALmixerData); |
7523 s_listOfALmixerData = NULL; | 7583 s_listOfALmixerData = NULL; |
7524 | 7584 |
7525 | 7585 |
8538 } | 8598 } |
8539 return( DoLoad(sample, buffersize, decode_mode_is_predecoded, max_queue_buffers, num_startup_buffers, access_data)); | 8599 return( DoLoad(sample, buffersize, decode_mode_is_predecoded, max_queue_buffers, num_startup_buffers, access_data)); |
8540 } | 8600 } |
8541 | 8601 |
8542 | 8602 |
8543 | |
8544 | |
8545 void ALmixer_FreeData(ALmixer_Data* data) | 8603 void ALmixer_FreeData(ALmixer_Data* data) |
8546 { | 8604 { |
8547 ALenum error; | 8605 if(AL_FALSE == ALmixer_Initialized) |
8548 if(NULL == data) | |
8549 { | 8606 { |
8550 return; | 8607 return; |
8551 } | 8608 } |
8552 | 8609 |
8553 if(AL_FALSE == ALmixer_Initialized) | |
8554 { | |
8555 return; | |
8556 } | |
8557 | |
8558 /* Bypass if in interruption event */ | 8610 /* Bypass if in interruption event */ |
8611 /* 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. */ | |
8559 if(NULL == alcGetCurrentContext()) | 8612 if(NULL == alcGetCurrentContext()) |
8560 { | 8613 { |
8561 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"); | 8614 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"); |
8562 return; | 8615 return; |
8563 } | 8616 } |
8564 | 8617 |
8565 if(data->decoded_all) | 8618 Internal_FreeData(data); |
8566 { | |
8567 /* If access_data was enabled, then the Sound_Sample* | |
8568 * still exists. We need to free it | |
8569 */ | |
8570 if(data->sample != NULL) | |
8571 { | |
8572 Sound_FreeSample(data->sample); | |
8573 } | |
8574 alDeleteBuffers(1, data->buffer); | |
8575 if((error = alGetError()) != AL_NO_ERROR) | |
8576 { | |
8577 fprintf(stderr, "ALmixer_FreeData: alDeleteBuffers failed. %s\n", alGetString(error)); | |
8578 } | |
8579 } | |
8580 else | |
8581 { | |
8582 ALuint i; | |
8583 | |
8584 /* Delete buffer copies if access_data was enabled */ | |
8585 if(data->buffer_map_list != NULL) | |
8586 { | |
8587 for(i=0; i<data->max_queue_buffers; i++) | |
8588 { | |
8589 free(data->buffer_map_list[i].data); | |
8590 } | |
8591 free(data->buffer_map_list); | |
8592 } | |
8593 if(data->circular_buffer_queue != NULL) | |
8594 { | |
8595 CircularQueueUnsignedInt_FreeQueue(data->circular_buffer_queue); | |
8596 } | |
8597 | |
8598 Sound_FreeSample(data->sample); | |
8599 alDeleteBuffers(data->max_queue_buffers, data->buffer); | |
8600 if((error = alGetError()) != AL_NO_ERROR) | |
8601 { | |
8602 fprintf(stderr, "ALmixer_FreeData: alDeleteBuffers failed. %s\n", alGetString(error)); | |
8603 } | |
8604 } | |
8605 free(data->buffer); | |
8606 | |
8607 LinkedList_Remove(s_listOfALmixerData, | |
8608 LinkedList_Find(s_listOfALmixerData, data, NULL) | |
8609 ); | |
8610 | |
8611 free(data); | |
8612 } | 8619 } |
8613 | 8620 |
8614 ALint ALmixer_GetTotalTime(ALmixer_Data* data) | 8621 ALint ALmixer_GetTotalTime(ALmixer_Data* data) |
8615 { | 8622 { |
8616 if(NULL == data) | 8623 if(NULL == data) |