# sdl12-compat: FIXME removal: Wrap event processing in a mutex.

**URL:** <https://discourse.libsdl.org/t/sdl12-compat-fixme-removal-wrap-event-processing-in-a-mutex/38262>\
**Category:** SDL Commits\
**Created:** [August 18, 2022, 1:48pm UTC](https://discourse.libsdl.org/t/sdl12-compat-fixme-removal-wrap-event-processing-in-a-mutex/38262 "2022-08-18T13:48:02Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![SDLPushPostBot](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/sdlpushpostbot/32/4370_2.png) [@SDLPushPostBot](https://discourse.libsdl.org/u/SDLPushPostBot)\
**Post date:** [August 18, 2022, 1:48pm UTC](https://discourse.libsdl.org/t/sdl12-compat-fixme-removal-wrap-event-processing-in-a-mutex/38262/1 "2022-08-18T13:48:02Z")

</div>

> <https://github.com/libsdl-org/sdl12-compat/commit/a219db64b584d6b8be97f26b14cbcc9c51ae2d60>
>
> Reference Issue #143.

```diff
From a219db64b584d6b8be97f26b14cbcc9c51ae2d60 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Thu, 18 Aug 2022 09:46:49 -0400
Subject: [PATCH] FIXME removal: Wrap event processing in a mutex.

Reference Issue #143.
---
 src/SDL12_compat.c | 129 ++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 109 insertions(+), 20 deletions(-)

diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index e31c5ef9..108ab9b9 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -1005,7 +1005,6 @@ static GLuint OpenGLCurrentReadFBO = 0;
 static GLuint OpenGLCurrentDrawFBO = 0;
 static SDL_bool ForceGLSwapBufferContext = SDL_FALSE;
 
-/* !!! FIXME: need a mutex for the event queue. */
 #define SDL12_MAXEVENTS 128
 typedef struct EventQueueType
 {
@@ -1014,6 +1013,7 @@ typedef struct EventQueueType
     struct EventQueueType *next;
 } EventQueueType;
 
+static SDL_mutex *EventQueueMutex = NULL;
 static EventQueueType EventQueuePool[SDL12_MAXEVENTS];
 static EventQueueType *EventQueueHead = NULL;
 static EventQueueType *EventQueueTail = NULL;
@@ -2143,8 +2143,14 @@ Init12Video(void)
 
     IsDummyVideo = ((driver != NULL) && (SDL20_strcmp(driver, "dummy") == 0)) ? SDL_TRUE : SDL_FALSE;
 
- for (i = 0; i < SDL12_MAXEVENTS-1; i++)
+ EventQueueMutex = SDL20_CreateMutex();
+ if (EventQueueMutex == NULL) {
+ return -1;
+ }
+
+ for (i = 0; i < SDL12_MAXEVENTS-1; i++) {
         EventQueuePool[i].next = &EventQueuePool[i+1];
+ }
     EventQueuePool[SDL12_MAXEVENTS-1].next = NULL;
 
     EventQueueHead = EventQueueTail = NULL;
@@ -2365,6 +2371,11 @@ Quit12Video(void)
     SDL_FreeCursor(CurrentCursor12);
     VideoModes = NULL;
     VideoModesCount = 0;
+
+ if (EventQueueMutex) {
+ SDL20_DestroyMutex(EventQueueMutex);
+ EventQueueMutex = NULL;
+ }
 }
 
 DECLSPEC void SDLCALL
@@ -2481,8 +2492,9 @@ SDL_VideoDriverName(char *namebuf, int maxlen)
 }
 
 
-DECLSPEC int SDLCALL
-SDL_PollEvent(SDL12_Event *event12)
+/* you MUST hold EventQueueMutex before calling this! */
+static int
+SDL_PollEvent_locked(SDL12_Event *event12)
 {
     EventQueueType *next;
 
@@ -2507,7 +2519,24 @@ SDL_PollEvent(SDL12_Event *event12)
 }
 
 DECLSPEC int SDLCALL
-SDL_PushEvent(SDL12_Event *event12)
+SDL_PollEvent(SDL12_Event *event12)
+{
+ int retval;
+
+ if (!EventQueueMutex) {
+ return 0;
+ }
+
+ SDL20_LockMutex(EventQueueMutex);
+ retval = SDL_PollEvent_locked(event12);
+ SDL20_UnlockMutex(EventQueueMutex);
+
+ return retval;
+}
+
+/* you MUST hold EventQueueMutex before calling this! */
+static int
+SDL_PushEvent_locked(SDL12_Event *event12)
 {
     EventQueueType *item = EventQueueAvailable;
     if (item == NULL) {
@@ -2534,7 +2563,25 @@ SDL_PushEvent(SDL12_Event *event12)
 }
 
 DECLSPEC int SDLCALL
-SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
+SDL_PushEvent(SDL12_Event *event12)
+{
+ int retval;
+
+ if (!EventQueueMutex) {
+ return SDL20_SetError("SDL not initialized");
+ }
+
+ SDL20_LockMutex(EventQueueMutex);
+ retval = SDL_PushEvent_locked(event12);
+ SDL20_UnlockMutex(EventQueueMutex);
+
+ return retval;
+}
+
+
+/* you MUST hold EventQueueMutex before calling this! */
+static int
+SDL_PeepEvents_locked(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
 {
     SDL12_Event dummy_event;
 
@@ -2608,46 +2655,78 @@ SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uin
     return 0;
 }
 
+DECLSPEC int SDLCALL
+SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
+{
+ int retval;
+
+ if (!EventQueueMutex) {
+ return SDL20_SetError("SDL not initialized");
+ }
+
+ SDL20_LockMutex(EventQueueMutex);
+ retval = SDL_PeepEvents_locked(events12, numevents, action, mask);
+ SDL20_UnlockMutex(EventQueueMutex);
+
+ return retval;
+}
+
 DECLSPEC int SDLCALL
 SDL_WaitEvent(SDL12_Event *event12)
 {
- FIXME("In 1.2, this only fails (-1) if you haven't SDL_Init()'d.");
+ if (!EventQueueMutex) {
+ return SDL20_SetError("SDL not initialized");
+ }
+
+ /* the 1.2 entry point for PollEvent will grab/release the EventQueueMutex */
     while (!SDL_PollEvent(event12)) {
         SDL20_Delay(10);
     }
+
     return 1;
 }
 
 static SDL_bool
 PushEventIfNotFiltered(SDL12_Event *event12)
 {
+ SDL_bool retval = SDL_FALSE;
     if (event12->type != SDL12_NOEVENT) {
+ SDL_assert(EventQueueMutex != NULL);
+ SDL20_LockMutex(EventQueueMutex);
         if (EventStates[event12->type] != SDL_IGNORE) {
             if ((!EventFilter12) || (EventFilter12(event12))) {
- return (SDL_PushEvent(event12) == 0)? SDL_TRUE : SDL_FALSE;
+ retval = (SDL_PushEvent(event12) == 0)? SDL_TRUE : SDL_FALSE;
             }
         }
+ SDL20_UnlockMutex(EventQueueMutex);
     }
- return SDL_FALSE;
+ return retval;
 }
 
 DECLSPEC Uint8 SDLCALL
 SDL_EventState(Uint8 type, int state)
 {
+ Uint8 retval = 0;
     /* the values of "state" match between 1.2 and 2.0 */
- const Uint8 retval = EventStates[type];
- SDL12_Event e;
+ if (EventQueueMutex) {
+ SDL12_Event e;
 
- if (state != SDL_QUERY) {
- EventStates[type] = state;
- if ((type == SDL12_SYSWMEVENT) && SupportSysWM) { /* we only enable syswm in SDL2 if it makes sense. */
- SDL20_EventState(SDL_SYSWMEVENT, state);
+ SDL20_LockMutex(EventQueueMutex);
+
+ retval = EventStates[type];
+ if (state != SDL_QUERY) {
+ EventStates[type] = state;
+ if ((type == SDL12_SYSWMEVENT) && SupportSysWM) { /* we only enable syswm in SDL2 if it makes sense. */
+ SDL20_EventState(SDL_SYSWMEVENT, state);
+ }
         }
- }
- if (state == SDL_IGNORE) { /* drop existing events of this type. */
- while (SDL_PeepEvents(&e, 1, SDL_GETEVENT, (1<<type))) {
- /* nothing */ ;
+ if (state == SDL_IGNORE) { /* drop existing events of this type. */
+ while (SDL_PeepEvents(&e, 1, SDL_GETEVENT, (1<<type))) {
+ /* nothing */ ;
+ }
         }
+
+ SDL20_UnlockMutex(EventQueueMutex);
     }
 
     return retval;
@@ -4092,7 +4171,7 @@ static int FlushPendingKeydownEvent(Uint32 unicode)
     PendingKeydownEvent.key.keysym.unicode = unicode;
     PushEventIfNotFiltered(&PendingKeydownEvent);
     /* Reset the event. */
- SDL20_memset(&PendingKeydownEvent, 0, sizeof(SDL12_Event));
+ SDL20_memset(&PendingKeydownEvent, 0, sizeof (SDL12_Event));
 
     return 1;
 }
@@ -6394,6 +6473,11 @@ SDL_PumpEvents(void)
     if (VideoSurfacePresentTicks && SDL_TICKS_PASSED(SDL20_GetTicks(), VideoSurfacePresentTicks)) {
         PresentScreen();
     }
+
+ if (EventQueueMutex) {
+ SDL20_LockMutex(EventQueueMutex);
+ }
+
     while (SDL20_PollEvent(&e)) { /* spin to drain the SDL2 event queue. */ }
 
     /* If there's a pending KEYDOWN event, and we haven't got a TEXTINPUT
@@ -6401,6 +6485,11 @@ SDL_PumpEvents(void)
     if (PendingKeydownEvent.type == SDL12_KEYDOWN) {
         FlushPendingKeydownEvent(0);
     }
+
+ if (EventQueueMutex) {
+ SDL20_UnlockMutex(EventQueueMutex);
+ }
+
 }
 
 DECLSPEC void SDLCALL

```
