Made event and temporary string memory thread-local and added SDL_FreeEventMemory()
Fixes https://github.com/libsdl-org/SDL/issues/10283
This commit is contained in:
@@ -582,7 +582,6 @@ void SDL_Quit(void)
|
||||
*/
|
||||
SDL_memset(SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount));
|
||||
|
||||
SDL_FlushEventMemory(0);
|
||||
SDL_FreeEnvironmentMemory();
|
||||
|
||||
SDL_QuitMainThread();
|
||||
|
||||
@@ -123,6 +123,7 @@ SDL3_0.0.0 {
|
||||
SDL_FlushEvent;
|
||||
SDL_FlushEvents;
|
||||
SDL_FlushRenderer;
|
||||
SDL_FreeEventMemory;
|
||||
SDL_GDKSuspendComplete;
|
||||
SDL_GL_CreateContext;
|
||||
SDL_GL_DestroyContext;
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
#define SDL_FlushEvent SDL_FlushEvent_REAL
|
||||
#define SDL_FlushEvents SDL_FlushEvents_REAL
|
||||
#define SDL_FlushRenderer SDL_FlushRenderer_REAL
|
||||
#define SDL_FreeEventMemory SDL_FreeEventMemory_REAL
|
||||
#define SDL_GDKSuspendComplete SDL_GDKSuspendComplete_REAL
|
||||
#define SDL_GL_CreateContext SDL_GL_CreateContext_REAL
|
||||
#define SDL_GL_DestroyContext SDL_GL_DestroyContext_REAL
|
||||
|
||||
@@ -168,6 +168,7 @@ SDL_DYNAPI_PROC(int,SDL_FlushAudioStream,(SDL_AudioStream *a),(a),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_FlushEvent,(Uint32 a),(a),)
|
||||
SDL_DYNAPI_PROC(void,SDL_FlushEvents,(Uint32 a, Uint32 b),(a,b),)
|
||||
SDL_DYNAPI_PROC(int,SDL_FlushRenderer,(SDL_Renderer *a),(a),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_FreeEventMemory,(void),(),)
|
||||
SDL_DYNAPI_PROC(void,SDL_GDKSuspendComplete,(void),(),)
|
||||
SDL_DYNAPI_PROC(SDL_GLContext,SDL_GL_CreateContext,(SDL_Window *a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_GL_DestroyContext,(SDL_GLContext a),(a),return)
|
||||
|
||||
@@ -97,35 +97,79 @@ typedef struct SDL_EventMemory
|
||||
struct SDL_EventMemory *next;
|
||||
} SDL_EventMemory;
|
||||
|
||||
static SDL_Mutex *SDL_event_memory_lock;
|
||||
static SDL_EventMemory *SDL_event_memory_head;
|
||||
static SDL_EventMemory *SDL_event_memory_tail;
|
||||
typedef struct SDL_EventMemoryState
|
||||
{
|
||||
SDL_EventMemory *head;
|
||||
SDL_EventMemory *tail;
|
||||
} SDL_EventMemoryState;
|
||||
|
||||
static SDL_TLSID SDL_event_memory;
|
||||
|
||||
|
||||
static void SDL_CleanupEventMemory(void *data)
|
||||
{
|
||||
SDL_EventMemoryState *state = (SDL_EventMemoryState *)data;
|
||||
|
||||
while (state->head) {
|
||||
SDL_EventMemory *entry = state->head;
|
||||
state->head = entry->next;
|
||||
SDL_free(entry->memory);
|
||||
SDL_free(entry);
|
||||
}
|
||||
SDL_free(state);
|
||||
}
|
||||
|
||||
static SDL_EventMemoryState *SDL_GetEventMemoryState(SDL_bool create)
|
||||
{
|
||||
SDL_EventMemoryState *state;
|
||||
|
||||
state = SDL_GetTLS(&SDL_event_memory);
|
||||
if (!state) {
|
||||
if (!create) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state = (SDL_EventMemoryState *)SDL_calloc(1, sizeof(*state));
|
||||
if (!state) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SDL_SetTLS(&SDL_event_memory, state, SDL_CleanupEventMemory) < 0) {
|
||||
SDL_free(state);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void *SDL_FreeLater(void *memory)
|
||||
{
|
||||
SDL_EventMemoryState *state;
|
||||
|
||||
if (memory == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state = SDL_GetEventMemoryState(SDL_TRUE);
|
||||
if (!state) {
|
||||
return memory; // this is now a leak, but you probably have bigger problems if malloc failed.
|
||||
}
|
||||
|
||||
SDL_EventMemory *entry = (SDL_EventMemory *)SDL_malloc(sizeof(*entry));
|
||||
if (!entry) {
|
||||
return memory; // this is now a leak, but you probably have bigger problems if malloc failed. We could probably pool up and reuse entries, though.
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_event_memory_lock);
|
||||
{
|
||||
entry->eventID = SDL_last_event_id;
|
||||
entry->memory = memory;
|
||||
entry->next = NULL;
|
||||
entry->eventID = SDL_last_event_id;
|
||||
entry->memory = memory;
|
||||
entry->next = NULL;
|
||||
|
||||
if (SDL_event_memory_tail) {
|
||||
SDL_event_memory_tail->next = entry;
|
||||
} else {
|
||||
SDL_event_memory_head = entry;
|
||||
}
|
||||
SDL_event_memory_tail = entry;
|
||||
if (state->tail) {
|
||||
state->tail->next = entry;
|
||||
} else {
|
||||
state->head = entry;
|
||||
}
|
||||
SDL_UnlockMutex(SDL_event_memory_lock);
|
||||
state->tail = entry;
|
||||
|
||||
return memory;
|
||||
}
|
||||
@@ -143,31 +187,39 @@ const char *SDL_AllocateEventString(const char *string)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SDL_FlushEventMemory(Uint32 eventID)
|
||||
static void SDL_FlushEventMemory(Uint32 eventID)
|
||||
{
|
||||
SDL_LockMutex(SDL_event_memory_lock);
|
||||
{
|
||||
if (SDL_event_memory_head) {
|
||||
while (SDL_event_memory_head) {
|
||||
SDL_EventMemory *entry = SDL_event_memory_head;
|
||||
SDL_EventMemoryState *state;
|
||||
|
||||
if (eventID && (Sint32)(eventID - entry->eventID) < 0) {
|
||||
break;
|
||||
}
|
||||
state = SDL_GetEventMemoryState(SDL_FALSE);
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If you crash here, your application has memory corruption
|
||||
* or freed memory in an event, which is no longer necessary.
|
||||
*/
|
||||
SDL_event_memory_head = entry->next;
|
||||
SDL_free(entry->memory);
|
||||
SDL_free(entry);
|
||||
}
|
||||
if (!SDL_event_memory_head) {
|
||||
SDL_event_memory_tail = NULL;
|
||||
if (state->head) {
|
||||
while (state->head) {
|
||||
SDL_EventMemory *entry = state->head;
|
||||
|
||||
if (eventID && (Sint32)(eventID - entry->eventID) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* If you crash here, your application has memory corruption
|
||||
* or freed memory in an event, which is no longer necessary.
|
||||
*/
|
||||
state->head = entry->next;
|
||||
SDL_free(entry->memory);
|
||||
SDL_free(entry);
|
||||
}
|
||||
if (!state->head) {
|
||||
state->tail = NULL;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(SDL_event_memory_lock);
|
||||
}
|
||||
|
||||
void SDL_FreeEventMemory(void)
|
||||
{
|
||||
SDL_FlushEventMemory(0);
|
||||
}
|
||||
|
||||
#ifndef SDL_JOYSTICK_DISABLED
|
||||
@@ -697,10 +749,6 @@ void SDL_StopEventLoop(void)
|
||||
SDL_disabled_events[i] = NULL;
|
||||
}
|
||||
|
||||
if (SDL_event_memory_lock) {
|
||||
SDL_DestroyMutex(SDL_event_memory_lock);
|
||||
SDL_event_memory_lock = NULL;
|
||||
}
|
||||
if (SDL_event_watchers_lock) {
|
||||
SDL_DestroyMutex(SDL_event_watchers_lock);
|
||||
SDL_event_watchers_lock = NULL;
|
||||
@@ -746,14 +794,6 @@ int SDL_StartEventLoop(void)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (SDL_event_memory_lock == NULL) {
|
||||
SDL_event_memory_lock = SDL_CreateMutex();
|
||||
if (SDL_event_memory_lock == NULL) {
|
||||
SDL_UnlockMutex(SDL_EventQ.lock);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_THREADS_DISABLED */
|
||||
|
||||
SDL_EventQ.active = SDL_TRUE;
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
/* Start and stop the event processing loop */
|
||||
extern int SDL_StartEventLoop(void);
|
||||
extern void SDL_StopEventLoop(void);
|
||||
extern void SDL_FlushEventMemory(Uint32 eventID);
|
||||
extern void SDL_QuitInterrupt(void);
|
||||
|
||||
extern const char *SDL_AllocateEventString(const char *string);
|
||||
|
||||
Reference in New Issue
Block a user