Avoid holding the list lock when not needed

This commit is contained in:
Chris Robinson 2011-09-10 05:19:08 -07:00
parent 238a747414
commit b9448a476e
2 changed files with 173 additions and 119 deletions

262
Alc/ALc.c
View File

@ -369,8 +369,8 @@ static pthread_key_t LocalContext;
// Process-wide current context
static ALCcontext *GlobalContext;
// Context Error
static ALCenum g_eLastNullDeviceError = ALC_NO_ERROR;
/* Device Error */
static volatile ALCenum g_eLastNullDeviceError = ALC_NO_ERROR;
// Default context extensions
static const ALchar alExtList[] =
@ -1054,36 +1054,6 @@ static ALCboolean IsContext(ALCcontext *context)
}
/*
alcSetError
Store latest ALC Error
*/
ALCvoid alcSetError(ALCdevice *device, ALCenum errorCode)
{
if(TrapALCError)
{
#ifdef _WIN32
/* Safely catch a breakpoint exception that wasn't caught by a debugger */
__try {
DebugBreak();
} __except((GetExceptionCode()==EXCEPTION_BREAKPOINT) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
}
#elif defined(SIGTRAP)
kill(getpid(), SIGTRAP);
#endif
}
LockLists();
if(IsDevice(device))
device->LastError = errorCode;
else
g_eLastNullDeviceError = errorCode;
UnlockLists();
}
/* UpdateDeviceParams:
*
* Updates device parameters according to the attribute list.
@ -1379,6 +1349,57 @@ void ALCdevice_DecRef(ALCdevice *device)
if(ref == 0) FreeDevice(device);
}
/* VerifyDevice
*
* Verifies that the device handle is valid, and increments its ref count if
* so.
*/
static ALCdevice *VerifyDevice(ALCdevice *device)
{
ALCdevice *tmpDevice;
if(!device)
return NULL;
LockLists();
tmpDevice = g_pDeviceList;
while(tmpDevice && tmpDevice != device)
tmpDevice = tmpDevice->next;
if(tmpDevice)
ALCdevice_IncRef(tmpDevice);
UnlockLists();
return tmpDevice;
}
/* alcSetError
*
* Store latest ALC Error
*/
ALCvoid alcSetError(ALCdevice *device, ALCenum errorCode)
{
if(TrapALCError)
{
#ifdef _WIN32
/* Safely catch a breakpoint exception that wasn't caught by a debugger */
__try {
DebugBreak();
} __except((GetExceptionCode()==EXCEPTION_BREAKPOINT) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
}
#elif defined(SIGTRAP)
kill(getpid(), SIGTRAP);
#endif
}
if(device)
device->LastError = errorCode;
else
g_eLastNullDeviceError = errorCode;
}
/*
InitContext
@ -1663,50 +1684,49 @@ ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
{
LockLists();
if(!IsDevice(device) || !device->IsCaptureDevice)
if(!(device=VerifyDevice(device)) || !device->IsCaptureDevice)
{
alcSetError(device, ALC_INVALID_DEVICE);
UnlockLists();
if(device) ALCdevice_DecRef(device);
return;
}
LockDevice(device);
UnlockLists();
if(device->Connected)
ALCdevice_StartCapture(device);
UnlockDevice(device);
ALCdevice_DecRef(device);
}
ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
{
LockLists();
if(!IsDevice(device) || !device->IsCaptureDevice)
if(!(device=VerifyDevice(device)) || !device->IsCaptureDevice)
{
alcSetError(device, ALC_INVALID_DEVICE);
UnlockLists();
if(device) ALCdevice_DecRef(device);
return;
}
LockDevice(device);
UnlockLists();
if(device->Connected)
ALCdevice_StopCapture(device);
UnlockDevice(device);
ALCdevice_DecRef(device);
}
ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
{
LockLists();
if(!IsDevice(device) || !device->IsCaptureDevice)
if(!(device=VerifyDevice(device)) || !device->IsCaptureDevice)
{
alcSetError(device, ALC_INVALID_DEVICE);
UnlockLists();
if(device) ALCdevice_DecRef(device);
return;
}
LockDevice(device);
UnlockLists();
if(device->Connected)
ALCdevice_CaptureSamples(device, buffer, samples);
UnlockDevice(device);
ALCdevice_DecRef(device);
}
/*
@ -1718,18 +1738,14 @@ ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
{
ALCenum errorCode;
LockLists();
if(IsDevice(device))
if(VerifyDevice(device))
{
errorCode = device->LastError;
device->LastError = ALC_NO_ERROR;
errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
ALCdevice_DecRef(device);
}
else
{
errorCode = g_eLastNullDeviceError;
g_eLastNullDeviceError = ALC_NO_ERROR;
}
UnlockLists();
errorCode = ExchangeInt(&g_eLastNullDeviceError, ALC_NO_ERROR);
return errorCode;
}
@ -1792,15 +1808,16 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum para
break;
case ALC_DEVICE_SPECIFIER:
LockLists();
if(IsDevice(pDevice))
if(VerifyDevice(pDevice))
{
value = pDevice->szDeviceName;
ALCdevice_DecRef(pDevice);
}
else
{
ProbeDeviceList();
value = alcDeviceList;
}
UnlockLists();
break;
case ALC_ALL_DEVICES_SPECIFIER:
@ -1809,19 +1826,22 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum para
break;
case ALC_CAPTURE_DEVICE_SPECIFIER:
LockLists();
if(IsDevice(pDevice))
if(VerifyDevice(pDevice))
{
value = pDevice->szDeviceName;
ALCdevice_DecRef(pDevice);
}
else
{
ProbeCaptureDeviceList();
value = alcCaptureDeviceList;
}
UnlockLists();
break;
/* Default devices are always first in the list */
case ALC_DEFAULT_DEVICE_SPECIFIER:
pDevice = VerifyDevice(pDevice);
if(!alcDeviceList)
ProbeDeviceList();
@ -1829,10 +1849,14 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum para
alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");
if(!alcDefaultDeviceSpecifier)
alcSetError(pDevice, ALC_OUT_OF_MEMORY);
value = alcDefaultDeviceSpecifier;
if(pDevice) ALCdevice_DecRef(pDevice);
break;
case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
pDevice = VerifyDevice(pDevice);
if(!alcAllDeviceList)
ProbeAllDeviceList();
@ -1841,10 +1865,14 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum para
alcAllDeviceList : "");
if(!alcDefaultAllDeviceSpecifier)
alcSetError(pDevice, ALC_OUT_OF_MEMORY);
value = alcDefaultAllDeviceSpecifier;
if(pDevice) ALCdevice_DecRef(pDevice);
break;
case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
pDevice = VerifyDevice(pDevice);
if(!alcCaptureDeviceList)
ProbeCaptureDeviceList();
@ -1853,20 +1881,25 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum para
alcCaptureDeviceList : "");
if(!alcCaptureDefaultDeviceSpecifier)
alcSetError(pDevice, ALC_OUT_OF_MEMORY);
value = alcCaptureDefaultDeviceSpecifier;
if(pDevice) ALCdevice_DecRef(pDevice);
break;
case ALC_EXTENSIONS:
LockLists();
if(IsDevice(pDevice))
value = alcExtensionList;
else
if(!VerifyDevice(pDevice))
value = alcNoDeviceExtList;
UnlockLists();
else
{
value = alcExtensionList;
ALCdevice_DecRef(pDevice);
}
break;
default:
pDevice = VerifyDevice(pDevice);
alcSetError(pDevice, ALC_INVALID_ENUM);
if(pDevice) ALCdevice_DecRef(pDevice);
break;
}
@ -1881,14 +1914,16 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum para
*/
ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
{
device = VerifyDevice(device);
if(size == 0 || data == NULL)
{
alcSetError(device, ALC_INVALID_VALUE);
if(device) ALCdevice_DecRef(device);
return;
}
LockLists();
if(!IsDevice(device))
if(!device)
{
switch(param)
{
@ -2053,7 +2088,8 @@ ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsi
break;
}
}
UnlockLists();
if(device)
ALCdevice_DecRef(device);
}
@ -2065,19 +2101,15 @@ ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsi
ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
{
ALCboolean bResult = ALC_FALSE;
const char *ptr;
size_t len;
device = VerifyDevice(device);
if(!extName)
{
alcSetError(device, ALC_INVALID_VALUE);
return ALC_FALSE;
}
len = strlen(extName);
LockLists();
ptr = (IsDevice(device) ? alcExtensionList : alcNoDeviceExtList);
UnlockLists();
else
{
size_t len = strlen(extName);
const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
while(ptr && *ptr)
{
if(strncasecmp(ptr, extName, len) == 0 &&
@ -2093,7 +2125,9 @@ ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const A
} while(isspace(*ptr));
}
}
}
if(device)
ALCdevice_DecRef(device);
return bResult;
}
@ -2105,17 +2139,22 @@ ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const A
*/
ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
{
ALsizei i = 0;
ALCvoid *ptr = NULL;
device = VerifyDevice(device);
if(!funcName)
{
alcSetError(device, ALC_INVALID_VALUE);
return NULL;
}
else
{
ALsizei i = 0;
while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName,funcName) != 0)
i++;
return alcFunctions[i].address;
ptr = alcFunctions[i].address;
}
if(device)
ALCdevice_DecRef(device);
return ptr;
}
@ -2126,17 +2165,22 @@ ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar
*/
ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
{
ALsizei i = 0;
ALCenum val = 0;
device = VerifyDevice(device);
if(!enumName)
{
alcSetError(device, ALC_INVALID_VALUE);
return (ALCenum)0;
}
else
{
ALsizei i = 0;
while(enumeration[i].enumName && strcmp(enumeration[i].enumName,enumName) != 0)
i++;
return enumeration[i].value;
val = enumeration[i].value;
}
if(device)
ALCdevice_DecRef(device);
return val;
}
@ -2150,21 +2194,23 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
ALCcontext *ALContext;
LockLists();
if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected)
if(!(device=VerifyDevice(device)) || device->IsCaptureDevice || !device->Connected)
{
alcSetError(device, ALC_INVALID_DEVICE);
UnlockLists();
alcSetError(device, ALC_INVALID_DEVICE);
if(device) ALCdevice_DecRef(device);
return NULL;
}
// Reset Context Last Error code
/* Reset Context Last Error code */
device->LastError = ALC_NO_ERROR;
if(UpdateDeviceParams(device, attrList) == ALC_FALSE)
{
UnlockLists();
alcSetError(device, ALC_INVALID_DEVICE);
aluHandleDisconnect(device);
UnlockLists();
ALCdevice_DecRef(device);
return NULL;
}
@ -2179,28 +2225,32 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
}
if(!ALContext || !ALContext->ActiveSources)
{
free(ALContext);
alcSetError(device, ALC_OUT_OF_MEMORY);
if(device->NumContexts == 0)
{
ALCdevice_StopPlayback(device);
device->Flags &= ~DEVICE_RUNNING;
}
UnlockLists();
free(ALContext);
ALContext = NULL;
alcSetError(device, ALC_OUT_OF_MEMORY);
ALCdevice_DecRef(device);
return NULL;
}
ALContext->Device = device;
InitContext(ALContext);
LockDevice(device);
UnlockLists();
device->NumContexts++;
ALContext->next = device->ContextList;
device->ContextList = ALContext;
device->NumContexts++;
InitContext(ALContext);
UnlockDevice(device);
UnlockLists();
ALCdevice_DecRef(device);
return ALContext;
}
@ -2647,7 +2697,9 @@ ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device
ALCboolean ret = ALC_FALSE;
LockLists();
if(!IsDevice(device) || !device->IsLoopbackDevice)
if(!IsDevice(device))
alcSetError(NULL, ALC_INVALID_DEVICE);
else if(!device->IsLoopbackDevice)
alcSetError(device, ALC_INVALID_DEVICE);
else if(freq <= 0)
alcSetError(device, ALC_INVALID_VALUE);
@ -2667,7 +2719,9 @@ ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device
ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
{
LockLists();
if(!IsDevice(device) || !device->IsLoopbackDevice)
if(!IsDevice(device))
alcSetError(NULL, ALC_INVALID_DEVICE);
else if(!device->IsLoopbackDevice)
alcSetError(device, ALC_INVALID_DEVICE);
else if(samples < 0 || (samples > 0 && buffer == NULL))
alcSetError(device, ALC_INVALID_VALUE);

View File

@ -529,7 +529,7 @@ struct ALCdevice_struct
ALCchar *szDeviceName;
ALCenum LastError;
volatile ALCenum LastError;
// Maximum number of sources that can be created
ALuint MaxNoOfSources;