diff --git a/src/SDL.c b/src/SDL.c index d5a1288509..0116ba9c30 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -252,21 +252,14 @@ void SDL_InitMainThread(void) { SDL_InitTLSData(); SDL_InitEnvironment(); - SDL_InitProperties(); - SDL_InitHints(); SDL_InitTicks(); SDL_InitFilesystem(); - SDL_InitLog(); - SDL_GetGlobalProperties(); } static void SDL_QuitMainThread(void) { - SDL_QuitLog(); SDL_QuitFilesystem(); SDL_QuitTicks(); - SDL_QuitHints(); - SDL_QuitProperties(); SDL_QuitEnvironment(); SDL_QuitTLSData(); } @@ -625,6 +618,10 @@ void SDL_Quit(void) */ SDL_memset(SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount)); + SDL_QuitLog(); + SDL_QuitHints(); + SDL_QuitProperties(); + SDL_QuitMainThread(); SDL_bInMainQuit = false; diff --git a/src/SDL_hints.c b/src/SDL_hints.c index 8dd9c551cc..2d1d5b872a 100644 --- a/src/SDL_hints.c +++ b/src/SDL_hints.c @@ -36,20 +36,37 @@ typedef struct SDL_Hint SDL_HintWatch *callbacks; } SDL_Hint; -static SDL_PropertiesID SDL_hint_props = 0; +static SDL_AtomicU32 SDL_hint_props; -static SDL_PropertiesID GetHintProperties(bool create) -{ - if (!SDL_hint_props && create) { - SDL_hint_props = SDL_CreateProperties(); - } - return SDL_hint_props; -} void SDL_InitHints(void) { - // Just make sure the hint properties are created on the main thread - (void)GetHintProperties(true); +} + +void SDL_QuitHints(void) +{ + SDL_PropertiesID props; + do { + props = SDL_GetAtomicU32(&SDL_hint_props); + } while (!SDL_CompareAndSwapAtomicU32(&SDL_hint_props, props, 0)); + + if (props) { + SDL_DestroyProperties(props); + } +} + +static SDL_PropertiesID GetHintProperties(bool create) +{ + SDL_PropertiesID props = SDL_GetAtomicU32(&SDL_hint_props); + if (!props && create) { + props = SDL_CreateProperties(); + if (!SDL_CompareAndSwapAtomicU32(&SDL_hint_props, 0, props)) { + // Somebody else created hint properties before us, just use those + SDL_DestroyProperties(props); + props = SDL_GetAtomicU32(&SDL_hint_props); + } + } + return props; } static void SDLCALL CleanupHintProperty(void *userdata, void *value) @@ -336,9 +353,3 @@ void SDL_RemoveHintCallback(const char *name, SDL_HintCallback callback, void *u SDL_UnlockProperties(hints); } -void SDL_QuitHints(void) -{ - SDL_DestroyProperties(SDL_hint_props); - SDL_hint_props = 0; -} - diff --git a/src/SDL_properties.c b/src/SDL_properties.c index 2a4f2aca83..eacbc588f4 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -48,10 +48,11 @@ typedef struct SDL_Mutex *lock; } SDL_Properties; +static SDL_InitState SDL_properties_init; static SDL_HashTable *SDL_properties; static SDL_Mutex *SDL_properties_lock; static SDL_PropertiesID SDL_last_properties_id; -static SDL_PropertiesID SDL_global_properties; +static SDL_AtomicU32 SDL_global_properties; static void SDL_FreePropertyWithCleanup(const void *key, const void *value, void *data, bool cleanup) @@ -99,27 +100,42 @@ static void SDL_FreeProperties(const void *key, const void *value, void *data) bool SDL_InitProperties(void) { - if (!SDL_properties_lock) { - SDL_properties_lock = SDL_CreateMutex(); - if (!SDL_properties_lock) { - return false; - } + if (!SDL_ShouldInit(&SDL_properties_init)) { + return true; } + + // If this fails we'll continue without it. + SDL_properties_lock = SDL_CreateMutex(); + + SDL_properties = SDL_CreateHashTable(NULL, 16, SDL_HashID, SDL_KeyMatchID, SDL_FreeProperties, false); if (!SDL_properties) { - SDL_properties = SDL_CreateHashTable(NULL, 16, SDL_HashID, SDL_KeyMatchID, SDL_FreeProperties, false); - if (!SDL_properties) { - return false; - } + goto error; } + + SDL_SetInitialized(&SDL_properties_init, true); return true; + +error: + SDL_SetInitialized(&SDL_properties_init, true); + SDL_QuitProperties(); + return false; } void SDL_QuitProperties(void) { - if (SDL_global_properties) { - SDL_DestroyProperties(SDL_global_properties); - SDL_global_properties = 0; + if (!SDL_ShouldQuit(&SDL_properties_init)) { + return; } + + SDL_PropertiesID props; + do { + props = SDL_GetAtomicU32(&SDL_global_properties); + } while (!SDL_CompareAndSwapAtomicU32(&SDL_global_properties, props, 0)); + + if (props) { + SDL_DestroyProperties(props); + } + if (SDL_properties) { SDL_DestroyHashTable(SDL_properties); SDL_properties = NULL; @@ -128,14 +144,27 @@ void SDL_QuitProperties(void) SDL_DestroyMutex(SDL_properties_lock); SDL_properties_lock = NULL; } + + SDL_SetInitialized(&SDL_properties_init, false); +} + +static bool SDL_CheckInitProperties(void) +{ + return SDL_InitProperties(); } SDL_PropertiesID SDL_GetGlobalProperties(void) { - if (!SDL_global_properties) { - SDL_global_properties = SDL_CreateProperties(); + SDL_PropertiesID props = SDL_GetAtomicU32(&SDL_global_properties); + if (!props) { + props = SDL_CreateProperties(); + if (!SDL_CompareAndSwapAtomicU32(&SDL_global_properties, 0, props)) { + // Somebody else created global properties before us, just use those + SDL_DestroyProperties(props); + props = SDL_GetAtomicU32(&SDL_global_properties); + } } - return SDL_global_properties; + return props; } SDL_PropertiesID SDL_CreateProperties(void) @@ -144,7 +173,7 @@ SDL_PropertiesID SDL_CreateProperties(void) SDL_Properties *properties = NULL; bool inserted = false; - if (!SDL_properties && !SDL_InitProperties()) { + if (!SDL_CheckInitProperties()) { return 0; } @@ -156,14 +185,9 @@ SDL_PropertiesID SDL_CreateProperties(void) if (!properties->props) { goto error; } - properties->lock = SDL_CreateMutex(); - if (!properties->lock) { - goto error; - } - if (!SDL_InitProperties()) { - goto error; - } + // If this fails we'll continue without it. + properties->lock = SDL_CreateMutex(); SDL_LockMutex(SDL_properties_lock); ++SDL_last_properties_id;