Don't automatically free temporary memory, let the application call SDL_FreeTemporaryMemory() when it's ready.

Also mark up all functions that return temporary memory with SDL_DECLSPEC_TEMP, to help people implementing language bindings.

Fixes https://github.com/libsdl-org/SDL/issues/10378
This commit is contained in:
Sam Lantinga
2024-07-26 06:05:57 -07:00
parent 2f38a4bf5e
commit 5e513ecc7f
31 changed files with 124 additions and 402 deletions

View File

@@ -130,6 +130,7 @@ SDL3_0.0.0 {
SDL_FlushEvent;
SDL_FlushEvents;
SDL_FlushRenderer;
SDL_FreeTemporaryMemory;
SDL_GDKSuspendComplete;
SDL_GL_CreateContext;
SDL_GL_DestroyContext;

View File

@@ -155,6 +155,7 @@
#define SDL_FlushEvent SDL_FlushEvent_REAL
#define SDL_FlushEvents SDL_FlushEvents_REAL
#define SDL_FlushRenderer SDL_FlushRenderer_REAL
#define SDL_FreeTemporaryMemory SDL_FreeTemporaryMemory_REAL
#define SDL_GDKSuspendComplete SDL_GDKSuspendComplete_REAL
#define SDL_GL_CreateContext SDL_GL_CreateContext_REAL
#define SDL_GL_DestroyContext SDL_GL_DestroyContext_REAL

View File

@@ -175,6 +175,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_FreeTemporaryMemory,(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)

View File

@@ -197,6 +197,7 @@ def main():
func_ret = func_ret.replace('extern', ' ')
func_ret = func_ret.replace('SDLCALL', ' ')
func_ret = func_ret.replace('SDL_DECLSPEC', ' ')
func_ret = func_ret.replace('SDL_DECLSPEC_TEMP', ' ')
# Remove trailing spaces in front of '*'
tmp = ""
while func_ret != tmp:

View File

@@ -79,7 +79,6 @@ static Uint32 SDL_userevents = SDL_EVENT_USER;
typedef struct SDL_TemporaryMemory
{
void *memory;
Uint64 timestamp;
struct SDL_TemporaryMemory *prev;
struct SDL_TemporaryMemory *next;
} SDL_TemporaryMemory;
@@ -111,7 +110,6 @@ static struct
SDL_EventEntry *free;
} SDL_EventQ = { NULL, SDL_FALSE, { 0 }, 0, NULL, NULL, NULL };
static void SDL_FreeTemporaryMemory(void);
static void SDL_CleanupTemporaryMemory(void *data)
{
@@ -268,23 +266,6 @@ static void SDL_TransferTemporaryMemoryFromEvent(SDL_EventEntry *event)
event->memory = NULL;
}
static void SDL_CollectTemporaryMemory(SDL_TemporaryMemoryState *state, Uint64 now)
{
// Temporary memory will age out and be collected after 1 second
const int TEMPORARY_MEMORY_COLLECT_TIME_MS = 1000;
while (state->head) {
SDL_TemporaryMemory *entry = state->head;
if ((now - entry->timestamp) < TEMPORARY_MEMORY_COLLECT_TIME_MS) {
break;
}
SDL_UnlinkTemporaryMemoryEntry(state, entry);
SDL_FreeTemporaryMemoryEntry(state, entry, SDL_TRUE);
}
}
void *SDL_FreeLater(void *memory)
{
SDL_TemporaryMemoryState *state;
@@ -301,16 +282,12 @@ void *SDL_FreeLater(void *memory)
return memory; // this is now a leak, but you probably have bigger problems if malloc failed.
}
Uint64 now = SDL_GetTicks();
SDL_CollectTemporaryMemory(state, now);
SDL_TemporaryMemory *entry = (SDL_TemporaryMemory *)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.
}
entry->memory = memory;
entry->timestamp = now;
SDL_LinkTemporaryMemoryEntry(state, entry);
@@ -885,8 +862,6 @@ void SDL_StopEventLoop(void)
SDL_EventQ.free = NULL;
SDL_AtomicSet(&SDL_sentinel_pending, 0);
SDL_FreeTemporaryMemory();
/* Clear disabled event state */
for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) {
SDL_free(SDL_disabled_events[i]);
@@ -1183,9 +1158,6 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType)
/* Run the system dependent event loops */
static void SDL_PumpEventsInternal(SDL_bool push_sentinel)
{
/* Free old event memory */
SDL_FreeTemporaryMemory();
/* Release any keys held down from last frame */
SDL_ReleaseAutoReleaseKeys();