Properly destroy contexts that are left on the device when it's closed
This commit is contained in:
parent
419294cddd
commit
3dcd1e793e
83
Alc/ALc.c
83
Alc/ALc.c
@ -1485,6 +1485,43 @@ static ALCvoid FreeContext(ALCcontext *context)
|
|||||||
free(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)
|
void ALCcontext_IncRef(ALCcontext *context)
|
||||||
{
|
{
|
||||||
RefCount ref;
|
RefCount ref;
|
||||||
@ -2260,7 +2297,6 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
|
|||||||
ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
|
ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
|
||||||
{
|
{
|
||||||
ALCdevice *Device;
|
ALCdevice *Device;
|
||||||
ALCcontext *volatile*tmp_ctx;
|
|
||||||
|
|
||||||
LockLists();
|
LockLists();
|
||||||
Device = alcGetContextsDevice(context);
|
Device = alcGetContextsDevice(context);
|
||||||
@ -2270,35 +2306,7 @@ ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp_ctx = &Device->ContextList;
|
ReleaseContext(context, Device);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!Device->ContextList)
|
if(!Device->ContextList)
|
||||||
{
|
{
|
||||||
@ -2306,8 +2314,6 @@ ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
|
|||||||
Device->Flags &= ~DEVICE_RUNNING;
|
Device->Flags &= ~DEVICE_RUNNING;
|
||||||
}
|
}
|
||||||
UnlockLists();
|
UnlockLists();
|
||||||
|
|
||||||
ALCcontext_DecRef(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2605,14 +2611,17 @@ ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *pDevice)
|
|||||||
|
|
||||||
*list = (*list)->next;
|
*list = (*list)->next;
|
||||||
g_ulDeviceCount--;
|
g_ulDeviceCount--;
|
||||||
|
|
||||||
UnlockLists();
|
UnlockLists();
|
||||||
|
|
||||||
while((ctx=pDevice->ContextList) != NULL)
|
if((ctx=pDevice->ContextList) != NULL)
|
||||||
{
|
{
|
||||||
WARN("Destroying context %p\n", ctx);
|
do {
|
||||||
alcDestroyContext(ctx);
|
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_ClosePlayback(pDevice);
|
||||||
|
|
||||||
ALCdevice_DecRef(pDevice);
|
ALCdevice_DecRef(pDevice);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user