SDL3pp
A slim C++ wrapper for SDL3
|
A helpful assertion macro! More...
Macros | |
#define | SDL_ASSERT_LEVEL SomeNumberBasedOnVariousFactors |
The level of assertion aggressiveness. | |
#define | SDL_TriggerBreakpoint() TriggerABreakpointInAPlatformSpecificManner |
Attempt to tell an attached debugger to pause. | |
#define | SDL_FUNCTION __FUNCTION__ |
A macro that reports the current function being compiled. | |
#define | SDL_FILE __FILE__ |
A macro that reports the current file being compiled. | |
#define | SDL_LINE __LINE__ |
A macro that reports the current line number of the file being compiled. | |
#define | SDL_NULL_WHILE_LOOP_CONDITION (0) |
A macro for wrapping code in do {} while (0); without compiler warnings. | |
#define | SDL_disabled_assert(condition) |
The macro used when an assertion is disabled. | |
#define | SDL_AssertBreakpoint() SDL_TriggerBreakpoint() |
The macro used when an assertion triggers a breakpoint. | |
#define | SDL_enabled_assert(condition) |
The macro used when an assertion is enabled. | |
#define | SDL_assert(condition) if (assertion_enabled && (condition)) { trigger_assertion; } |
An assertion test that is normally performed only in debug builds. | |
#define | SDL_assert_release(condition) SDL_disabled_assert(condition) |
An assertion test that is performed even in release builds. | |
#define | SDL_assert_paranoid(condition) SDL_disabled_assert(condition) |
An assertion test that is performed only when built with paranoid settings. | |
#define | SDL_assert_always(condition) SDL_enabled_assert(condition) |
An assertion test that is always performed. | |
Typedefs | |
using | SDL::AssertState = SDL_AssertState |
Possible outcomes from a triggered assertion. | |
using | SDL::AssertData = SDL_AssertData |
Information about an assertion failure. | |
using | SDL::AssertionHandler = SDL_AssertionHandler |
A Callback that fires when an SDL assertion fails. | |
using | SDL::AssertionHandlerCB = std::function< SDL_AssertState(const SDL_AssertData *)> |
A callback that fires when an SDL assertion fails. | |
Functions | |
AssertState | SDL::ReportAssertion (AssertData *data, StringParam func, StringParam file, int line) |
Never call this directly. | |
void | SDL::SetAssertionHandler (AssertionHandler handler, void *userdata) |
Set an application-defined assertion handler. | |
void | SDL::SetAssertionHandler (AssertionHandlerCB handler) |
Set an application-defined assertion handler. | |
AssertionHandler | SDL::GetDefaultAssertionHandler () |
Get the default assertion handler. | |
AssertionHandler | SDL::GetAssertionHandler (void **puserdata) |
Get the current assertion handler. | |
AssertionHandlerCB | SDL::GetAssertionHandler () |
Get the current assertion handler. | |
const AssertData * | SDL::GetAssertionReport () |
Get a list of all assertion failures. | |
void | SDL::ResetAssertionReport () |
Clear the list of all assertion failures. | |
Variables | |
constexpr AssertState | SDL::ASSERTION_RETRY = SDL_ASSERTION_RETRY |
Retry the assert immediately. | |
constexpr AssertState | SDL::ASSERTION_BREAK = SDL_ASSERTION_BREAK |
Make the debugger trigger a breakpoint. | |
constexpr AssertState | SDL::ASSERTION_ABORT = SDL_ASSERTION_ABORT |
Terminate the program. | |
constexpr AssertState | SDL::ASSERTION_IGNORE = SDL_ASSERTION_IGNORE |
Ignore the assert. | |
constexpr AssertState | SDL::ASSERTION_ALWAYS_IGNORE = SDL_ASSERTION_ALWAYS_IGNORE |
Ignore the assert from now on. | |
SDL assertions operate like your usual assert
macro, but with some added features:
sizeof
operator, so disabled assertions vaporize out of the compiled code, but variables only referenced in the assertion won't trigger compiler warnings about being unused.if (x) SDL_assert(y); else do_something();
To use it: compile a debug build and just sprinkle around tests to check your code!
#define SDL_assert | ( | condition | ) | if (assertion_enabled && (condition)) { trigger_assertion; } |
This macro is enabled when the SDL_ASSERT_LEVEL is >= 2, otherwise it is disabled. This is meant to only do these tests in debug builds, so they can tend to be more expensive, and they are meant to bring everything to a halt when they fail, with the programmer there to assess the problem.
In short: you can sprinkle these around liberally and assume they will evaporate out of the build when building for end-users.
When assertions are disabled, this wraps condition
in a sizeof
operator, which means any function calls and side effects will not run, but the compiler will not complain about any otherwise-unused variables that are only referenced in the assertion.
One can set the environment variable "SDL_ASSERT" to one of several strings ("abort", "break", "retry", "ignore", "always_ignore") to force a default behavior, which may be desirable for automation purposes. If your platform requires GUI interfaces to happen on the main thread but you're debugging an assertion in a background thread, it might be desirable to set this to "break" so that your debugger takes control as soon as assert is triggered, instead of risking a bad UI interaction (deadlock, etc) in the application.
condition | boolean value to test. |
#define SDL_assert_always | ( | condition | ) | SDL_enabled_assert(condition) |
This macro is always enabled no matter what SDL_ASSERT_LEVEL is set to. You almost never want to use this, as it could trigger on an end-user's system, crashing your program.
One can set the environment variable "SDL_ASSERT" to one of several strings ("abort", "break", "retry", "ignore", "always_ignore") to force a default behavior, which may be desirable for automation purposes. If your platform requires GUI interfaces to happen on the main thread but you're debugging an assertion in a background thread, it might be desirable to set this to "break" so that your debugger takes control as soon as assert is triggered, instead of risking a bad UI interaction (deadlock, etc) in the application.
condition | boolean value to test. |
#define SDL_ASSERT_LEVEL SomeNumberBasedOnVariousFactors |
This value changes depending on compiler options and other preprocessor defines.
It is currently one of the following values, but future SDL releases might add more:
#define SDL_assert_paranoid | ( | condition | ) | SDL_disabled_assert(condition) |
This macro is enabled when the SDL_ASSERT_LEVEL is >= 3, otherwise it is disabled. This is a higher level than both release and debug, so these tests are meant to be expensive and only run when specifically looking for extremely unexpected failure cases in a special build.
When assertions are disabled, this wraps condition
in a sizeof
operator, which means any function calls and side effects will not run, but the compiler will not complain about any otherwise-unused variables that are only referenced in the assertion.
One can set the environment variable "SDL_ASSERT" to one of several strings ("abort", "break", "retry", "ignore", "always_ignore") to force a default behavior, which may be desirable for automation purposes. If your platform requires GUI interfaces to happen on the main thread but you're debugging an assertion in a background thread, it might be desirable to set this to "break" so that your debugger takes control as soon as assert is triggered, instead of risking a bad UI interaction (deadlock, etc) in the application.
condition | boolean value to test. |
#define SDL_assert_release | ( | condition | ) | SDL_disabled_assert(condition) |
This macro is enabled when the SDL_ASSERT_LEVEL is >= 1, otherwise it is disabled. This is meant to be for tests that are cheap to make and extremely unlikely to fail; generally it is frowned upon to have an assertion failure in a release build, so these assertions generally need to be of more than life-and-death importance if there's a chance they might trigger. You should almost always consider handling these cases more gracefully than an assert allows.
When assertions are disabled, this wraps condition
in a sizeof
operator, which means any function calls and side effects will not run, but the compiler will not complain about any otherwise-unused variables that are only referenced in the assertion.
One can set the environment variable "SDL_ASSERT" to one of several strings ("abort", "break", "retry", "ignore", "always_ignore") to force a default behavior, which may be desirable for automation purposes. If your platform requires GUI interfaces to happen on the main thread but you're debugging an assertion in a background thread, it might be desirable to set this to "break" so that your debugger takes control as soon as assert is triggered, instead of risking a bad UI interaction (deadlock, etc) in the application.
condition | boolean value to test. |
#define SDL_AssertBreakpoint | ( | ) | SDL_TriggerBreakpoint() |
This isn't for direct use by apps; use SDL_assert or SDL_TriggerBreakpoint instead.
#define SDL_disabled_assert | ( | condition | ) |
This isn't for direct use by apps, but this is the code that is inserted when an SDL_assert is disabled (perhaps in a release build).
The code does nothing, but wraps condition
in a sizeof operator, which generates no code and has no side effects, but avoid compiler warnings about unused variables.
condition | the condition to assert (but not actually run here). |
#define SDL_enabled_assert | ( | condition | ) |
This isn't for direct use by apps, but this is the code that is inserted when an SDL_assert is enabled.
The do {} while(0)
avoids dangling else problems:
... without the do/while, the "else" could attach to this macro's "if". We try to handle just the minimum we need here in a macro...the loop, the static vars, and break points. The heavy lifting is handled in SDL_ReportAssertion().
condition | the condition to assert. |
#define SDL_FILE __FILE__ |
#define SDL_FUNCTION __FUNCTION__ |
#define SDL_LINE __LINE__ |
#define SDL_NULL_WHILE_LOOP_CONDITION (0) |
Visual Studio with really aggressive warnings enabled needs this to avoid compiler complaints.
the do {} while (0);
trick is useful for wrapping code in a macro that may or may not be a single statement, to avoid various C language accidents.
To use:
#define SDL_TriggerBreakpoint | ( | ) | TriggerABreakpointInAPlatformSpecificManner |
This allows an app to programmatically halt ("break") the debugger as if it had hit a breakpoint, allowing the developer to examine program state, etc.
This is a macro–not a function–so that the debugger breaks on the source code line that used SDL_TriggerBreakpoint and not in some random guts of SDL. SDL_assert uses this macro for the same reason.
If the program is not running under a debugger, SDL_TriggerBreakpoint will likely terminate the app, possibly without warning. If the current platform isn't supported, this macro is left undefined.
using SDL::AssertData = typedef SDL_AssertData |
This structure is filled in with information about a triggered assertion, used by the assertion handler, then added to the assertion report. This is returned as a linked list from SDL_GetAssertionReport().
using SDL::AssertionHandler = typedef SDL_AssertionHandler |
data | a pointer to the SDL_AssertData structure corresponding to the current assertion. |
userdata | what was passed as userdata to SetAssertionHandler(). |
using SDL::AssertionHandlerCB = typedef std::function<SDL_AssertState(const SDL_AssertData*)> |
data | a pointer to the AssertData structure corresponding to the current assertion. |
using SDL::AssertState = typedef SDL_AssertState |
When an enabled assertion triggers, it may call the assertion handler (possibly one provided by the app via SDL_SetAssertionHandler), which will return one of these values, possibly after asking the user.
Then SDL will respond based on this outcome (loop around to retry the condition, try to break in a debugger, kill the program, or ignore the problem).
|
inline |
This returns the function pointer that is called when an assertion is triggered. This is either the value last passed to SDL_SetAssertionHandler(), or if no application-specified function is set, is equivalent to calling SDL_GetDefaultAssertionHandler().
The parameter puserdata
is a pointer to a void*, which will store the "userdata" pointer that was passed to SDL_SetAssertionHandler(). This value will always be nullptr for the default handler. If you don't care about this data, it is safe to pass a nullptr pointer to this function to ignore it.
|
inline |
This returns the function pointer that is called when an assertion is triggered. This is either the value last passed to SDL_SetAssertionHandler(), or if no application-specified function is set, is equivalent to calling GetDefaultAssertionHandler().
The parameter puserdata
is a pointer to a void*, which will store the "userdata" pointer that was passed to SetAssertionHandler(). This value will always be nullptr for the default handler. If you don't care about this data, it is safe to pass a nullptr pointer to this function to ignore it.
puserdata | pointer which is filled with the "userdata" pointer that was passed to SetAssertionHandler(). |
|
inline |
This function gets all assertions triggered since the last call to SDL_ResetAssertionReport(), or the start of the program.
The proper way to examine this data looks something like this:
|
inline |
This returns the function pointer that is called by default when an assertion is triggered. This is an internal function provided by SDL, that is used for assertions when SetAssertionHandler() hasn't been used to provide a different function.
|
inline |
Use the SDL_assert macros instead.
data | assert data structure. |
func | function name. |
file | file name. |
line | line number. |
|
inline |
This function will clear the list of all assertions triggered up to that point. Immediately following this call, SDL_GetAssertionReport will return no items. In addition, any previously-triggered assertions will be reset to a trigger_count of zero, and their always_ignore state will be false.
|
inline |
This function allows an application to show its own assertion UI and/or force the response to an assertion failure. If the application doesn't provide this, SDL will try to do the right thing, popping up a system-specific GUI dialog, and probably minimizing any fullscreen windows.
This callback may fire from any thread, but it runs wrapped in a mutex, so it will only fire from one thread at a time.
This callback is NOT reset to SDL's internal handler upon Quit()!
handler | the SDL_AssertionHandler function to call when an assertion fails or nullptr for the default handler. |
userdata | a pointer that is passed to handler . |
|
inline |
This function allows an application to show its own assertion UI and/or force the response to an assertion failure. If the application doesn't provide this, SDL will try to do the right thing, popping up a system-specific GUI dialog, and probably minimizing any fullscreen windows.
This callback may fire from any thread, but it runs wrapped in a mutex, so it will only fire from one thread at a time.
This callback is NOT reset to SDL's internal handler upon SDL_Quit()!
handler | the SDL_AssertionHandler function to call when an assertion fails. |