Skip to content

Commit

Permalink
Exposed the joystick locking functions for multi-threaded access to t…
Browse files Browse the repository at this point in the history
…he joystick API
  • Loading branch information
slouken committed Oct 10, 2017
1 parent 2657dfa commit d90fce3
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 45 deletions.
14 changes: 14 additions & 0 deletions include/SDL_joystick.h
Expand Up @@ -106,6 +106,20 @@ typedef enum
} SDL_JoystickPowerLevel;

/* Function prototypes */

/**
* Locking for multi-threaded access to the joystick API
*
* If you are using the joystick API or handling events from multiple threads
* you should use these locking functions to protect access to the joysticks.
*
* In particular, you are guaranteed that the joystick list won't change, so
* the API functions that take a joystick index will be valid, and joystick
* and game controller events will not be delivered.
*/
extern DECLSPEC void SDLCALL SDL_LockJoysticks(void);
extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void);

/**
* Count the number of joysticks attached to the system right now
*/
Expand Down
2 changes: 2 additions & 0 deletions src/dynapi/SDL_dynapi_overrides.h
Expand Up @@ -635,3 +635,5 @@
#define SDL_Vulkan_GetInstanceExtensions SDL_Vulkan_GetInstanceExtensions_REAL
#define SDL_Vulkan_CreateSurface SDL_Vulkan_CreateSurface_REAL
#define SDL_Vulkan_GetDrawableSize SDL_Vulkan_GetDrawableSize_REAL
#define SDL_LockJoysticks SDL_LockJoysticks_REAL
#define SDL_UnlockJoysticks SDL_UnlockJoysticks_REAL
2 changes: 2 additions & 0 deletions src/dynapi/SDL_dynapi_procs.h
Expand Up @@ -669,3 +669,5 @@ SDL_DYNAPI_PROC(void,SDL_Vulkan_UnloadLibrary,(void),(),)
SDL_DYNAPI_PROC(SDL_bool,SDL_Vulkan_GetInstanceExtensions,(SDL_Window *a, unsigned int *b, const char **c),(a,b,c),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_Vulkan_CreateSurface,(SDL_Window *a, VkInstance b, VkSurfaceKHR *c),(a,b,c),return)
SDL_DYNAPI_PROC(void,SDL_Vulkan_GetDrawableSize,(SDL_Window *a, int *b, int *c),(a,b,c),)
SDL_DYNAPI_PROC(void,SDL_LockJoysticks,(void),(),)
SDL_DYNAPI_PROC(void,SDL_UnlockJoysticks,(void),(),)
38 changes: 19 additions & 19 deletions src/joystick/SDL_gamecontroller.c
Expand Up @@ -24,9 +24,9 @@

#include "SDL_events.h"
#include "SDL_assert.h"
#include "SDL_hints.h"
#include "SDL_sysjoystick.h"
#include "SDL_joystick_c.h"
#include "SDL_hints.h"
#include "SDL_gamecontrollerdb.h"

#if !SDL_EVENTS_DISABLED
Expand Down Expand Up @@ -910,7 +910,7 @@ static ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index)
SDL_JoystickGUID guid;
ControllerMapping_t *mapping;

SDL_LockJoystickList();
SDL_LockJoysticks();
name = SDL_JoystickNameForIndex(device_index);
guid = SDL_JoystickGetDeviceGUID(device_index);
mapping = SDL_PrivateGetControllerMappingForNameAndGUID(name, guid);
Expand All @@ -919,7 +919,7 @@ static ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index)
mapping = s_pXInputMapping;
}
#endif
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return mapping;
}

Expand Down Expand Up @@ -1349,15 +1349,15 @@ SDL_GameControllerOpen(int device_index)
return (NULL);
}

SDL_LockJoystickList();
SDL_LockJoysticks();

gamecontrollerlist = SDL_gamecontrollers;
/* If the controller is already open, return it */
while (gamecontrollerlist) {
if (SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == gamecontrollerlist->joystick->instance_id) {
gamecontroller = gamecontrollerlist;
++gamecontroller->ref_count;
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return (gamecontroller);
}
gamecontrollerlist = gamecontrollerlist->next;
Expand All @@ -1367,22 +1367,22 @@ SDL_GameControllerOpen(int device_index)
pSupportedController = SDL_PrivateGetControllerMapping(device_index);
if (!pSupportedController) {
SDL_SetError("Couldn't find mapping for device (%d)", device_index);
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return NULL;
}

/* Create and initialize the controller */
gamecontroller = (SDL_GameController *) SDL_calloc(1, sizeof(*gamecontroller));
if (gamecontroller == NULL) {
SDL_OutOfMemory();
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return NULL;
}

gamecontroller->joystick = SDL_JoystickOpen(device_index);
if (!gamecontroller->joystick) {
SDL_free(gamecontroller);
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return NULL;
}

Expand All @@ -1392,7 +1392,7 @@ SDL_GameControllerOpen(int device_index)
SDL_OutOfMemory();
SDL_JoystickClose(gamecontroller->joystick);
SDL_free(gamecontroller);
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return NULL;
}
}
Expand All @@ -1403,7 +1403,7 @@ SDL_GameControllerOpen(int device_index)
SDL_JoystickClose(gamecontroller->joystick);
SDL_free(gamecontroller->last_match_axis);
SDL_free(gamecontroller);
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return NULL;
}
}
Expand All @@ -1416,7 +1416,7 @@ SDL_GameControllerOpen(int device_index)
gamecontroller->next = SDL_gamecontrollers;
SDL_gamecontrollers = gamecontroller;

SDL_UnlockJoystickList();
SDL_UnlockJoysticks();

return (gamecontroller);
}
Expand Down Expand Up @@ -1589,16 +1589,16 @@ SDL_GameControllerFromInstanceID(SDL_JoystickID joyid)
{
SDL_GameController *gamecontroller;

SDL_LockJoystickList();
SDL_LockJoysticks();
gamecontroller = SDL_gamecontrollers;
while (gamecontroller) {
if (gamecontroller->joystick->instance_id == joyid) {
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return gamecontroller;
}
gamecontroller = gamecontroller->next;
}
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return NULL;
}

Expand Down Expand Up @@ -1674,11 +1674,11 @@ SDL_GameControllerClose(SDL_GameController * gamecontroller)
if (!gamecontroller)
return;

SDL_LockJoystickList();
SDL_LockJoysticks();

/* First decrement ref count */
if (--gamecontroller->ref_count > 0) {
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return;
}

Expand All @@ -1705,7 +1705,7 @@ SDL_GameControllerClose(SDL_GameController * gamecontroller)
SDL_free(gamecontroller->last_hat_mask);
SDL_free(gamecontroller);

SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
}


Expand All @@ -1715,12 +1715,12 @@ SDL_GameControllerClose(SDL_GameController * gamecontroller)
void
SDL_GameControllerQuit(void)
{
SDL_LockJoystickList();
SDL_LockJoysticks();
while (SDL_gamecontrollers) {
SDL_gamecontrollers->ref_count = 1;
SDL_GameControllerClose(SDL_gamecontrollers);
}
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
}

void
Expand Down
44 changes: 22 additions & 22 deletions src/joystick/SDL_joystick.c
Expand Up @@ -40,15 +40,15 @@ static SDL_bool SDL_updating_joystick = SDL_FALSE;
static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */

void
SDL_LockJoystickList(void)
SDL_LockJoysticks(void)
{
if (SDL_joystick_lock) {
SDL_LockMutex(SDL_joystick_lock);
}
}

void
SDL_UnlockJoystickList(void)
SDL_UnlockJoysticks(void)
{
if (SDL_joystick_lock) {
SDL_UnlockMutex(SDL_joystick_lock);
Expand Down Expand Up @@ -168,7 +168,7 @@ SDL_JoystickOpen(int device_index)
return (NULL);
}

SDL_LockJoystickList();
SDL_LockJoysticks();

joysticklist = SDL_joysticks;
/* If the joystick is already open, return it
Expand All @@ -178,7 +178,7 @@ SDL_JoystickOpen(int device_index)
if (SDL_JoystickGetDeviceInstanceID(device_index) == joysticklist->instance_id) {
joystick = joysticklist;
++joystick->ref_count;
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return (joystick);
}
joysticklist = joysticklist->next;
Expand All @@ -188,13 +188,13 @@ SDL_JoystickOpen(int device_index)
joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1);
if (joystick == NULL) {
SDL_OutOfMemory();
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return NULL;
}

if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) {
SDL_free(joystick);
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return NULL;
}

Expand Down Expand Up @@ -222,7 +222,7 @@ SDL_JoystickOpen(int device_index)
|| ((joystick->nbuttons > 0) && !joystick->buttons)) {
SDL_OutOfMemory();
SDL_JoystickClose(joystick);
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return NULL;
}
joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
Expand All @@ -244,7 +244,7 @@ SDL_JoystickOpen(int device_index)
joystick->next = SDL_joysticks;
SDL_joysticks = joystick;

SDL_UnlockJoystickList();
SDL_UnlockJoysticks();

SDL_SYS_JoystickUpdate(joystick);

Expand Down Expand Up @@ -460,14 +460,14 @@ SDL_JoystickFromInstanceID(SDL_JoystickID joyid)
{
SDL_Joystick *joystick;

SDL_LockJoystickList();
SDL_LockJoysticks();
for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
if (joystick->instance_id == joyid) {
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return joystick;
}
}
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return NULL;
}

Expand Down Expand Up @@ -497,16 +497,16 @@ SDL_JoystickClose(SDL_Joystick * joystick)
return;
}

SDL_LockJoystickList();
SDL_LockJoysticks();

/* First decrement ref count */
if (--joystick->ref_count > 0) {
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return;
}

if (SDL_updating_joystick) {
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return;
}

Expand Down Expand Up @@ -538,7 +538,7 @@ SDL_JoystickClose(SDL_Joystick * joystick)
SDL_free(joystick->buttons);
SDL_free(joystick);

SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
}

void
Expand All @@ -547,7 +547,7 @@ SDL_JoystickQuit(void)
/* Make sure we're not getting called in the middle of updating joysticks */
SDL_assert(!SDL_updating_joystick);

SDL_LockJoystickList();
SDL_LockJoysticks();

/* Stop the event polling */
while (SDL_joysticks) {
Expand All @@ -558,7 +558,7 @@ SDL_JoystickQuit(void)
/* Quit the joystick setup */
SDL_SYS_JoystickQuit();

SDL_UnlockJoystickList();
SDL_UnlockJoysticks();

#if !SDL_EVENTS_DISABLED
SDL_QuitSubSystem(SDL_INIT_EVENTS);
Expand Down Expand Up @@ -847,18 +847,18 @@ SDL_JoystickUpdate(void)
{
SDL_Joystick *joystick;

SDL_LockJoystickList();
SDL_LockJoysticks();

if (SDL_updating_joystick) {
/* The joysticks are already being updated */
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
return;
}

SDL_updating_joystick = SDL_TRUE;

/* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
SDL_UnlockJoystickList();
SDL_UnlockJoysticks();

for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
SDL_SYS_JoystickUpdate(joystick);
Expand All @@ -885,7 +885,7 @@ SDL_JoystickUpdate(void)
}
}

SDL_LockJoystickList();
SDL_LockJoysticks();

SDL_updating_joystick = SDL_FALSE;

Expand All @@ -901,7 +901,7 @@ SDL_JoystickUpdate(void)
*/
SDL_SYS_JoystickDetect();

SDL_UnlockJoystickList();
SDL_UnlockJoysticks();
}

int
Expand Down
4 changes: 0 additions & 4 deletions src/joystick/SDL_joystick_c.h
Expand Up @@ -33,10 +33,6 @@ extern void SDL_GameControllerQuitMappings(void);
extern int SDL_GameControllerInit(void);
extern void SDL_GameControllerQuit(void);

/* Locking for multi-threaded access to the joystick API */
extern void SDL_LockJoystickList(void);
extern void SDL_UnlockJoystickList(void);

/* Function to extract information from an SDL joystick GUID */
extern void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version);

Expand Down

0 comments on commit d90fce3

Please sign in to comment.