|
@@ -74,6 +74,7 @@ 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;
|
|
@@ -105,11 +106,13 @@ 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)
|
|
|
{
|
|
|
SDL_TemporaryMemoryState *state = (SDL_TemporaryMemoryState *)data;
|
|
|
|
|
|
- SDL_FreeTemporaryMemory(NULL);
|
|
|
+ SDL_FreeTemporaryMemory();
|
|
|
SDL_free(state);
|
|
|
}
|
|
|
|
|
@@ -260,6 +263,23 @@ 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;
|
|
@@ -276,12 +296,16 @@ 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);
|
|
|
|
|
@@ -317,7 +341,7 @@ void *SDL_ClaimTemporaryMemory(const void *mem)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-void SDL_FreeTemporaryMemory(const void *mem)
|
|
|
+void SDL_FreeTemporaryMemory(void)
|
|
|
{
|
|
|
SDL_TemporaryMemoryState *state;
|
|
|
|
|
@@ -326,19 +350,11 @@ void SDL_FreeTemporaryMemory(const void *mem)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (mem) {
|
|
|
- SDL_TemporaryMemory *entry = SDL_GetTemporaryMemoryEntry(state, mem);
|
|
|
- if (entry) {
|
|
|
- SDL_UnlinkTemporaryMemoryEntry(state, entry);
|
|
|
- SDL_FreeTemporaryMemoryEntry(state, entry, SDL_TRUE);
|
|
|
- }
|
|
|
- } else {
|
|
|
- while (state->head) {
|
|
|
- SDL_TemporaryMemory *entry = state->head;
|
|
|
+ while (state->head) {
|
|
|
+ SDL_TemporaryMemory *entry = state->head;
|
|
|
|
|
|
- SDL_UnlinkTemporaryMemoryEntry(state, entry);
|
|
|
- SDL_FreeTemporaryMemoryEntry(state, entry, SDL_TRUE);
|
|
|
- }
|
|
|
+ SDL_UnlinkTemporaryMemoryEntry(state, entry);
|
|
|
+ SDL_FreeTemporaryMemoryEntry(state, entry, SDL_TRUE);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -862,7 +878,7 @@ void SDL_StopEventLoop(void)
|
|
|
SDL_EventQ.free = NULL;
|
|
|
SDL_AtomicSet(&SDL_sentinel_pending, 0);
|
|
|
|
|
|
- SDL_FreeTemporaryMemory(NULL);
|
|
|
+ SDL_FreeTemporaryMemory();
|
|
|
|
|
|
/* Clear disabled event state */
|
|
|
for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) {
|
|
@@ -1159,7 +1175,7 @@ static void SDL_PumpEventsInternal(SDL_bool push_sentinel)
|
|
|
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
|
|
|
|
|
/* Free old event memory */
|
|
|
- SDL_FreeTemporaryMemory(NULL);
|
|
|
+ SDL_FreeTemporaryMemory();
|
|
|
|
|
|
/* Release any keys held down from last frame */
|
|
|
SDL_ReleaseAutoReleaseKeys();
|