aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/ALc.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2011-09-10 07:35:48 -0700
committerChris Robinson <[email protected]>2011-09-10 07:35:48 -0700
commit3dcd1e793e9548d1a8c477095e9f1eb388be61ce (patch)
treea2bafedeb9edcef7f0e0b022e672763d0c29444c /Alc/ALc.c
parent419294cddd7a437eb8d4bc5c0ffa6861d794d99b (diff)
Properly destroy contexts that are left on the device when it's closed
Diffstat (limited to 'Alc/ALc.c')
-rw-r--r--Alc/ALc.c83
1 files changed, 46 insertions, 37 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index a5296ced..e945d0b4 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -1485,6 +1485,43 @@ static ALCvoid FreeContext(ALCcontext *context)
free(context);
}
+static void ReleaseContext(ALCcontext *context, ALCdevice *device)
+{
+ ALCcontext *volatile*tmp_ctx;
+
+ tmp_ctx = &device->ContextList;
+ while(*tmp_ctx)
+ {
+ if(*tmp_ctx == context)
+ {
+ *tmp_ctx = context->next;
+ break;
+ }
+ tmp_ctx = &(*tmp_ctx)->next;
+ }
+
+ LockDevice(device);
+ /* Lock the device to make sure the mixer is not using the contexts in the
+ * list before we go about deleting this one. There should be a more
+ * efficient way of doing this. */
+ UnlockDevice(device);
+
+ if(pthread_getspecific(LocalContext) == context)
+ {
+ WARN("Context %p released while current on thread\n", context);
+ pthread_setspecific(LocalContext, NULL);
+ ALCcontext_DecRef(context);
+ }
+
+ if(CompExchangePtr((void**)&GlobalContext, context, NULL))
+ {
+ WARN("Context %p released while globally current\n", context);
+ ALCcontext_DecRef(context);
+ }
+
+ ALCcontext_DecRef(context);
+}
+
void ALCcontext_IncRef(ALCcontext *context)
{
RefCount ref;
@@ -2260,7 +2297,6 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
{
ALCdevice *Device;
- ALCcontext *volatile*tmp_ctx;
LockLists();
Device = alcGetContextsDevice(context);
@@ -2270,35 +2306,7 @@ ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
return;
}
- tmp_ctx = &Device->ContextList;
- while(*tmp_ctx)
- {
- if(*tmp_ctx == context)
- {
- *tmp_ctx = context->next;
- break;
- }
- tmp_ctx = &(*tmp_ctx)->next;
- }
-
- LockDevice(Device);
- /* Lock the device to make sure the mixer is not using the contexts in the
- * list before we go about deleting this one. There should be a more
- * efficient way of doing this. */
- UnlockDevice(Device);
-
- if(pthread_getspecific(LocalContext) == context)
- {
- WARN("Context %p destroyed while current on thread\n", context);
- pthread_setspecific(LocalContext, NULL);
- ALCcontext_DecRef(context);
- }
-
- if(CompExchangePtr((void**)&GlobalContext, context, NULL))
- {
- WARN("Context %p destroyed while globally current\n", context);
- ALCcontext_DecRef(context);
- }
+ ReleaseContext(context, Device);
if(!Device->ContextList)
{
@@ -2306,8 +2314,6 @@ ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
Device->Flags &= ~DEVICE_RUNNING;
}
UnlockLists();
-
- ALCcontext_DecRef(context);
}
@@ -2605,14 +2611,17 @@ ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *pDevice)
*list = (*list)->next;
g_ulDeviceCount--;
-
UnlockLists();
- while((ctx=pDevice->ContextList) != NULL)
+ if((ctx=pDevice->ContextList) != NULL)
{
- WARN("Destroying context %p\n", ctx);
- alcDestroyContext(ctx);
- }
+ do {
+ WARN("Destroying context %p\n", ctx);
+ ReleaseContext(ctx, pDevice);
+ } while((ctx=pDevice->ContextList) != NULL);
+ ALCdevice_StopPlayback(pDevice);
+ pDevice->Flags &= ~DEVICE_RUNNING;
+ };
ALCdevice_ClosePlayback(pDevice);
ALCdevice_DecRef(pDevice);