Improved sensor thread-safety

This fixes an issue where the main thread would hang indefinitely when polling events if sensors were initialized and shutdown on another thread.
This commit is contained in:
Sam Lantinga
2023-08-08 22:08:40 -07:00
parent 4ee0e5a984
commit 6b93e788fa
4 changed files with 204 additions and 112 deletions

View File

@@ -52,7 +52,6 @@ typedef struct
static ASensorManager *SDL_sensor_manager;
static ALooper *SDL_sensor_looper;
static SDL_AndroidSensorThreadContext SDL_sensor_thread_context;
static SDL_Mutex *SDL_sensors_lock;
static SDL_AndroidSensor *SDL_sensors SDL_GUARDED_BY(SDL_sensors_lock);
static int SDL_sensors_count;
@@ -72,7 +71,7 @@ static int SDLCALL SDL_ANDROID_SensorThread(void *data)
Uint64 timestamp = SDL_GetTicksNS();
if (ALooper_pollAll(-1, NULL, &events, (void **)&source) == LOOPER_ID_USER) {
SDL_LockMutex(SDL_sensors_lock);
SDL_LockSensors();
for (i = 0; i < SDL_sensors_count; ++i) {
if (!SDL_sensors[i].event_queue) {
continue;
@@ -83,7 +82,7 @@ static int SDLCALL SDL_ANDROID_SensorThread(void *data)
SDL_SendSensorUpdate(timestamp, SDL_sensors[i].sensor, timestamp, event.data, SDL_arraysize(event.data));
}
}
SDL_UnlockMutex(SDL_sensors_lock);
SDL_UnlockSensors();
}
}
@@ -138,11 +137,6 @@ static int SDL_ANDROID_SensorInit(void)
int i, sensors_count;
ASensorList sensors;
SDL_sensors_lock = SDL_CreateMutex();
if (!SDL_sensors_lock) {
return SDL_SetError("Couldn't create sensor lock");
}
SDL_sensor_manager = ASensorManager_getInstance();
if (SDL_sensor_manager == NULL) {
return SDL_SetError("Couldn't create sensor manager");
@@ -209,19 +203,19 @@ static int SDL_ANDROID_SensorOpen(SDL_Sensor *sensor, int device_index)
{
int delay_us, min_delay_us;
SDL_LockMutex(SDL_sensors_lock);
SDL_LockSensors();
{
SDL_sensors[device_index].sensor = sensor;
SDL_sensors[device_index].event_queue = ASensorManager_createEventQueue(SDL_sensor_manager, SDL_sensor_looper, LOOPER_ID_USER, NULL, NULL);
if (!SDL_sensors[device_index].event_queue) {
SDL_UnlockMutex(SDL_sensors_lock);
SDL_UnlockSensors();
return SDL_SetError("Couldn't create sensor event queue");
}
if (ASensorEventQueue_enableSensor(SDL_sensors[device_index].event_queue, SDL_sensors[device_index].asensor) < 0) {
ASensorManager_destroyEventQueue(SDL_sensor_manager, SDL_sensors[device_index].event_queue);
SDL_sensors[device_index].event_queue = NULL;
SDL_UnlockMutex(SDL_sensors_lock);
SDL_UnlockSensors();
return SDL_SetError("Couldn't enable sensor");
}
@@ -234,7 +228,7 @@ static int SDL_ANDROID_SensorOpen(SDL_Sensor *sensor, int device_index)
}
ASensorEventQueue_setEventRate(SDL_sensors[device_index].event_queue, SDL_sensors[device_index].asensor, delay_us);
}
SDL_UnlockMutex(SDL_sensors_lock);
SDL_UnlockSensors();
return 0;
}
@@ -249,14 +243,14 @@ static void SDL_ANDROID_SensorClose(SDL_Sensor *sensor)
for (i = 0; i < SDL_sensors_count; ++i) {
if (SDL_sensors[i].sensor == sensor) {
SDL_LockMutex(SDL_sensors_lock);
SDL_LockSensors();
{
ASensorEventQueue_disableSensor(SDL_sensors[i].event_queue, SDL_sensors[i].asensor);
ASensorManager_destroyEventQueue(SDL_sensor_manager, SDL_sensors[i].event_queue);
SDL_sensors[i].event_queue = NULL;
SDL_sensors[i].sensor = NULL;
}
SDL_UnlockMutex(SDL_sensors_lock);
SDL_UnlockSensors();
break;
}
}
@@ -271,11 +265,6 @@ static void SDL_ANDROID_SensorQuit(void)
SDL_sensors = NULL;
SDL_sensors_count = 0;
}
if (SDL_sensors_lock) {
SDL_DestroyMutex(SDL_sensors_lock);
SDL_sensors_lock = NULL;
}
}
SDL_SensorDriver SDL_ANDROID_SensorDriver = {