Added SDL_ShouldInit() and SDL_ShouldQuit()

These are handy functions to support thread-safe initialization and shutdown.
This commit is contained in:
Sam Lantinga
2024-09-26 15:49:59 -07:00
parent 0e2c4e407a
commit 125e592844
7 changed files with 178 additions and 52 deletions

View File

@@ -30,6 +30,7 @@
#include <SDL3/SDL_stdinc.h>
#include <SDL3/SDL_error.h>
#include <SDL3/SDL_thread.h>
/******************************************************************************/
/* Enable thread safety attributes only with clang.
@@ -757,6 +758,140 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WaitConditionTimeout(SDL_Condition *cond,
/* @} *//* Condition variable functions */
/**
* \name Thread-safe initialization state functions
*/
/* @{ */
/**
* The current status of an SDL_InitState structure.
*
* \since This enum is available since SDL 3.0.0.
*/
typedef enum SDL_InitStatus
{
SDL_INIT_STATUS_UNINITIALIZED,
SDL_INIT_STATUS_INITIALIZING,
SDL_INIT_STATUS_INITIALIZED,
SDL_INIT_STATUS_UNINITIALIZING
} SDL_InitStatus;
/**
* A structure used for thread-safe initialization and shutdown.
*
* Here is an example of using this:
*
* ```c
* static SDL_AtomicInitState init;
*
* bool InitSystem(void)
* {
* if (!SDL_ShouldInit(&init)) {
* // The system is initialized
* return true;
* }
*
* // At this point, you should not leave this function without calling SDL_SetInitialized()
*
* bool initialized = DoInitTasks();
* SDL_SetInitialized(&init, initialized);
* return initialized;
* }
*
* bool UseSubsystem(void)
* {
* if (SDL_ShouldInit(&init)) {
* // Error, the subsystem isn't initialized
* SDL_SetInitialized(&init, false);
* return false;
* }
*
* // Do work using the initialized subsystem
*
* return true;
* }
*
* void QuitSystem(void)
* {
* if (!SDL_ShouldQuit(&init)) {
* // The system is not initialized
* return true;
* }
*
* // At this point, you should not leave this function without calling SDL_SetInitialized()
*
* DoQuitTasks();
* SDL_SetInitialized(&init, false);
* }
* ```
*
* Note that this doesn't protect any resources created during initialization, or guarantee that nobody is using those resources during cleanup. You should use other mechanisms to protect those, if that's a concern for your code.
*
* \since This struct is available since SDL 3.0.0.
*/
typedef struct SDL_InitState
{
SDL_AtomicInt status;
SDL_ThreadID thread;
void *reserved;
} SDL_InitState;
/**
* Return whether initialization should be done.
*
* This function checks the passed in state and if initialization should be done, sets the status to `SDL_INIT_STATUS_INITIALIZING` and returns true. If another thread is already modifying this state, it will wait until that's done before returning.
*
* If this function returns true, the calling code must call SDL_SetInitialized() to complete the initialization.
*
* \param state the initialization state to check.
* \returns true if initialization needs to be done, false otherwise.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_SetInitialized
* \sa SDL_ShouldQuit
*/
extern SDL_DECLSPEC bool SDLCALL SDL_ShouldInit(SDL_InitState *state);
/**
* Return whether cleanup should be done.
*
* This function checks the passed in state and if cleanup should be done, sets the status to `SDL_INIT_STATUS_UNINITIALIZING` and returns true.
*
* If this function returns true, the calling code must call SDL_SetInitialized() to complete the cleanup.
*
* \param state the initialization state to check.
* \returns true if cleanup needs to be done, false otherwise.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_SetInitialized
* \sa SDL_ShouldInit
*/
extern SDL_DECLSPEC bool SDLCALL SDL_ShouldQuit(SDL_InitState *state);
/**
* Finish an initialization state transition.
*
* This function sets the status of the passed in state to `SDL_INIT_STATUS_INITIALIZED` or `SDL_INIT_STATUS_UNINITIALIZED` and allows any threads waiting for the status to proceed.
*
* \param state the initialization state to check.
* \param initialized the new initialization state.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_ShouldInit
* \sa SDL_ShouldQuit
*/
extern SDL_DECLSPEC void SDLCALL SDL_SetInitialized(SDL_InitState *state, bool initialized);
/* @} *//* Thread-safe initialization state functions */
/* Ends C function definitions when using C++ */
#ifdef __cplusplus