|
@@ -299,9 +299,11 @@ void UnrefPhysicalCamera(SDL_Camera *device)
|
|
|
{
|
|
|
if (SDL_AtomicDecRef(&device->refcount)) {
|
|
|
// take it out of the device list.
|
|
|
+ SDL_LockRWLockForWriting(camera_driver.device_hash_lock);
|
|
|
if (SDL_RemoveFromHashTable(camera_driver.device_hash, (const void *) (uintptr_t) device->instance_id)) {
|
|
|
SDL_AddAtomicInt(&camera_driver.device_count, -1);
|
|
|
}
|
|
|
+ SDL_UnlockRWLock(camera_driver.device_hash_lock);
|
|
|
DestroyPhysicalCamera(device); // ...and nuke it.
|
|
|
}
|
|
|
}
|
|
@@ -327,7 +329,9 @@ static SDL_Camera *ObtainPhysicalCamera(SDL_CameraID devid) // !!! FIXME: SDL_A
|
|
|
}
|
|
|
|
|
|
SDL_Camera *device = NULL;
|
|
|
+ SDL_LockRWLockForReading(camera_driver.device_hash_lock);
|
|
|
SDL_FindInHashTable(camera_driver.device_hash, (const void *) (uintptr_t) devid, (const void **) &device);
|
|
|
+ SDL_UnlockRWLock(camera_driver.device_hash_lock);
|
|
|
if (!device) {
|
|
|
SDL_SetError("Invalid camera device instance ID");
|
|
|
} else {
|
|
@@ -420,7 +424,9 @@ SDL_Camera *SDL_AddCamera(const char *name, SDL_CameraPosition position, int num
|
|
|
SDL_assert((specs != NULL) == (num_specs > 0));
|
|
|
SDL_assert(handle != NULL);
|
|
|
|
|
|
+ SDL_LockRWLockForReading(camera_driver.device_hash_lock);
|
|
|
const int shutting_down = SDL_GetAtomicInt(&camera_driver.shutting_down);
|
|
|
+ SDL_UnlockRWLock(camera_driver.device_hash_lock);
|
|
|
if (shutting_down) {
|
|
|
return NULL; // we're shutting down, don't add any devices that are hotplugged at the last possible moment.
|
|
|
}
|
|
@@ -490,6 +496,7 @@ SDL_Camera *SDL_AddCamera(const char *name, SDL_CameraPosition position, int num
|
|
|
SDL_SetAtomicInt(&device->zombie, 0);
|
|
|
RefPhysicalCamera(device);
|
|
|
|
|
|
+ SDL_LockRWLockForWriting(camera_driver.device_hash_lock);
|
|
|
if (SDL_InsertIntoHashTable(camera_driver.device_hash, (const void *) (uintptr_t) device->instance_id, device)) {
|
|
|
SDL_AddAtomicInt(&camera_driver.device_count, 1);
|
|
|
} else {
|
|
@@ -507,14 +514,13 @@ SDL_Camera *SDL_AddCamera(const char *name, SDL_CameraPosition position, int num
|
|
|
p->type = SDL_EVENT_CAMERA_DEVICE_ADDED;
|
|
|
p->devid = device->instance_id;
|
|
|
p->next = NULL;
|
|
|
- SDL_LockHashTable(camera_driver.device_hash, true);
|
|
|
SDL_assert(camera_driver.pending_events_tail != NULL);
|
|
|
SDL_assert(camera_driver.pending_events_tail->next == NULL);
|
|
|
camera_driver.pending_events_tail->next = p;
|
|
|
camera_driver.pending_events_tail = p;
|
|
|
- SDL_UnlockHashTable(camera_driver.device_hash);
|
|
|
}
|
|
|
}
|
|
|
+ SDL_UnlockRWLock(camera_driver.device_hash_lock);
|
|
|
|
|
|
return device;
|
|
|
}
|
|
@@ -568,12 +574,12 @@ void SDL_CameraDisconnected(SDL_Camera *device)
|
|
|
|
|
|
if (first_disconnect) {
|
|
|
if (pending.next) { // NULL if event is disabled or disaster struck.
|
|
|
- SDL_LockHashTable(camera_driver.device_hash, true);
|
|
|
+ SDL_LockRWLockForWriting(camera_driver.device_hash_lock);
|
|
|
SDL_assert(camera_driver.pending_events_tail != NULL);
|
|
|
SDL_assert(camera_driver.pending_events_tail->next == NULL);
|
|
|
camera_driver.pending_events_tail->next = pending.next;
|
|
|
camera_driver.pending_events_tail = pending_tail;
|
|
|
- SDL_UnlockHashTable(camera_driver.device_hash);
|
|
|
+ SDL_UnlockRWLock(camera_driver.device_hash_lock);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -606,12 +612,12 @@ void SDL_CameraPermissionOutcome(SDL_Camera *device, bool approved)
|
|
|
ReleaseCamera(device);
|
|
|
|
|
|
if (pending.next) { // NULL if event is disabled or disaster struck.
|
|
|
- SDL_LockHashTable(camera_driver.device_hash, true);
|
|
|
+ SDL_LockRWLockForWriting(camera_driver.device_hash_lock);
|
|
|
SDL_assert(camera_driver.pending_events_tail != NULL);
|
|
|
SDL_assert(camera_driver.pending_events_tail->next == NULL);
|
|
|
camera_driver.pending_events_tail->next = pending.next;
|
|
|
camera_driver.pending_events_tail = pending_tail;
|
|
|
- SDL_UnlockHashTable(camera_driver.device_hash);
|
|
|
+ SDL_UnlockRWLock(camera_driver.device_hash_lock);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -627,15 +633,16 @@ SDL_Camera *SDL_FindPhysicalCameraByCallback(bool (*callback)(SDL_Camera *device
|
|
|
const void *value;
|
|
|
void *iter = NULL;
|
|
|
|
|
|
- SDL_LockHashTable(camera_driver.device_hash, false);
|
|
|
+ SDL_LockRWLockForReading(camera_driver.device_hash_lock);
|
|
|
while (SDL_IterateHashTable(camera_driver.device_hash, &key, &value, &iter)) {
|
|
|
SDL_Camera *device = (SDL_Camera *) value;
|
|
|
if (callback(device, userdata)) { // found it?
|
|
|
- SDL_UnlockHashTable(camera_driver.device_hash);
|
|
|
+ SDL_UnlockRWLock(camera_driver.device_hash_lock);
|
|
|
return device;
|
|
|
}
|
|
|
}
|
|
|
- SDL_UnlockHashTable(camera_driver.device_hash);
|
|
|
+
|
|
|
+ SDL_UnlockRWLock(camera_driver.device_hash_lock);
|
|
|
|
|
|
SDL_SetError("Device not found");
|
|
|
return NULL;
|
|
@@ -709,7 +716,7 @@ SDL_CameraID *SDL_GetCameras(int *count)
|
|
|
|
|
|
SDL_CameraID *result = NULL;
|
|
|
|
|
|
- SDL_LockHashTable(camera_driver.device_hash, false);
|
|
|
+ SDL_LockRWLockForReading(camera_driver.device_hash_lock);
|
|
|
int num_devices = SDL_GetAtomicInt(&camera_driver.device_count);
|
|
|
result = (SDL_CameraID *) SDL_malloc((num_devices + 1) * sizeof (SDL_CameraID));
|
|
|
if (!result) {
|
|
@@ -726,7 +733,7 @@ SDL_CameraID *SDL_GetCameras(int *count)
|
|
|
SDL_assert(devs_seen == num_devices);
|
|
|
result[devs_seen] = 0; // null-terminated.
|
|
|
}
|
|
|
- SDL_UnlockHashTable(camera_driver.device_hash);
|
|
|
+ SDL_UnlockRWLock(camera_driver.device_hash_lock);
|
|
|
|
|
|
*count = num_devices;
|
|
|
|
|
@@ -1356,14 +1363,14 @@ void SDL_QuitCamera(void)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- SDL_HashTable *device_hash = camera_driver.device_hash;
|
|
|
- SDL_LockHashTable(device_hash, true);
|
|
|
+ SDL_LockRWLockForWriting(camera_driver.device_hash_lock);
|
|
|
SDL_SetAtomicInt(&camera_driver.shutting_down, 1);
|
|
|
+ SDL_HashTable *device_hash = camera_driver.device_hash;
|
|
|
camera_driver.device_hash = NULL;
|
|
|
SDL_PendingCameraEvent *pending_events = camera_driver.pending_events.next;
|
|
|
camera_driver.pending_events.next = NULL;
|
|
|
SDL_SetAtomicInt(&camera_driver.device_count, 0);
|
|
|
- SDL_UnlockHashTable(device_hash);
|
|
|
+ SDL_UnlockRWLock(camera_driver.device_hash_lock);
|
|
|
|
|
|
SDL_PendingCameraEvent *pending_next = NULL;
|
|
|
for (SDL_PendingCameraEvent *i = pending_events; i; i = pending_next) {
|
|
@@ -1381,6 +1388,7 @@ void SDL_QuitCamera(void)
|
|
|
// Free the driver data
|
|
|
camera_driver.impl.Deinitialize();
|
|
|
|
|
|
+ SDL_DestroyRWLock(camera_driver.device_hash_lock);
|
|
|
SDL_DestroyHashTable(device_hash);
|
|
|
|
|
|
SDL_zero(camera_driver);
|
|
@@ -1409,8 +1417,14 @@ bool SDL_CameraInit(const char *driver_name)
|
|
|
SDL_QuitCamera(); // shutdown driver if already running.
|
|
|
}
|
|
|
|
|
|
- SDL_HashTable *device_hash = SDL_CreateHashTable(NULL, 8, HashCameraID, MatchCameraID, NukeCameraHashItem, true, false);
|
|
|
+ SDL_RWLock *device_hash_lock = SDL_CreateRWLock(); // create this early, so if it fails we don't have to tear down the whole camera subsystem.
|
|
|
+ if (!device_hash_lock) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ SDL_HashTable *device_hash = SDL_CreateHashTable(NULL, 8, HashCameraID, MatchCameraID, NukeCameraHashItem, false, false);
|
|
|
if (!device_hash) {
|
|
|
+ SDL_DestroyRWLock(device_hash_lock);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
@@ -1427,6 +1441,7 @@ bool SDL_CameraInit(const char *driver_name)
|
|
|
const char *driver_attempt = driver_name_copy;
|
|
|
|
|
|
if (!driver_name_copy) {
|
|
|
+ SDL_DestroyRWLock(device_hash_lock);
|
|
|
SDL_DestroyHashTable(device_hash);
|
|
|
return false;
|
|
|
}
|
|
@@ -1442,6 +1457,7 @@ bool SDL_CameraInit(const char *driver_name)
|
|
|
tried_to_init = true;
|
|
|
SDL_zero(camera_driver);
|
|
|
camera_driver.pending_events_tail = &camera_driver.pending_events;
|
|
|
+ camera_driver.device_hash_lock = device_hash_lock;
|
|
|
camera_driver.device_hash = device_hash;
|
|
|
if (bootstrap[i]->init(&camera_driver.impl)) {
|
|
|
camera_driver.name = bootstrap[i]->name;
|
|
@@ -1465,6 +1481,7 @@ bool SDL_CameraInit(const char *driver_name)
|
|
|
tried_to_init = true;
|
|
|
SDL_zero(camera_driver);
|
|
|
camera_driver.pending_events_tail = &camera_driver.pending_events;
|
|
|
+ camera_driver.device_hash_lock = device_hash_lock;
|
|
|
camera_driver.device_hash = device_hash;
|
|
|
if (bootstrap[i]->init(&camera_driver.impl)) {
|
|
|
camera_driver.name = bootstrap[i]->name;
|
|
@@ -1485,6 +1502,7 @@ bool SDL_CameraInit(const char *driver_name)
|
|
|
}
|
|
|
|
|
|
SDL_zero(camera_driver);
|
|
|
+ SDL_DestroyRWLock(device_hash_lock);
|
|
|
SDL_DestroyHashTable(device_hash);
|
|
|
return false; // No driver was available, so fail.
|
|
|
}
|
|
@@ -1501,20 +1519,20 @@ bool SDL_CameraInit(const char *driver_name)
|
|
|
// ("UpdateSubsystem" is the same naming that the other things that hook into PumpEvents use.)
|
|
|
void SDL_UpdateCamera(void)
|
|
|
{
|
|
|
- SDL_LockHashTable(camera_driver.device_hash, false);
|
|
|
+ SDL_LockRWLockForReading(camera_driver.device_hash_lock);
|
|
|
SDL_PendingCameraEvent *pending_events = camera_driver.pending_events.next;
|
|
|
- SDL_UnlockHashTable(camera_driver.device_hash);
|
|
|
+ SDL_UnlockRWLock(camera_driver.device_hash_lock);
|
|
|
|
|
|
if (!pending_events) {
|
|
|
return; // nothing to do, check next time.
|
|
|
}
|
|
|
|
|
|
// okay, let's take this whole list of events so we can dump the lock, and new ones can queue up for a later update.
|
|
|
- SDL_LockHashTable(camera_driver.device_hash, true);
|
|
|
+ SDL_LockRWLockForWriting(camera_driver.device_hash_lock);
|
|
|
pending_events = camera_driver.pending_events.next; // in case this changed...
|
|
|
camera_driver.pending_events.next = NULL;
|
|
|
camera_driver.pending_events_tail = &camera_driver.pending_events;
|
|
|
- SDL_UnlockHashTable(camera_driver.device_hash);
|
|
|
+ SDL_UnlockRWLock(camera_driver.device_hash_lock);
|
|
|
|
|
|
SDL_PendingCameraEvent *pending_next = NULL;
|
|
|
for (SDL_PendingCameraEvent *i = pending_events; i; i = pending_next) {
|