| 1 | /* |
| 2 | Simple DirectMedia Layer |
| 3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> |
| 4 | |
| 5 | This software is provided 'as-is', without any express or implied |
| 6 | warranty. In no event will the authors be held liable for any damages |
| 7 | arising from the use of this software. |
| 8 | |
| 9 | Permission is granted to anyone to use this software for any purpose, |
| 10 | including commercial applications, and to alter it and redistribute it |
| 11 | freely, subject to the following restrictions: |
| 12 | |
| 13 | 1. The origin of this software must not be misrepresented; you must not |
| 14 | claim that you wrote the original software. If you use this software |
| 15 | in a product, an acknowledgment in the product documentation would be |
| 16 | appreciated but is not required. |
| 17 | 2. Altered source versions must be plainly marked as such, and must not be |
| 18 | misrepresented as being the original software. |
| 19 | 3. This notice may not be removed or altered from any source distribution. |
| 20 | */ |
| 21 | |
| 22 | /** |
| 23 | * # CategoryAssert |
| 24 | * |
| 25 | * A helpful assertion macro! |
| 26 | * |
| 27 | * SDL assertions operate like your usual `assert` macro, but with some added |
| 28 | * features: |
| 29 | * |
| 30 | * - It uses a trick with the `sizeof` operator, so disabled assertions |
| 31 | * vaporize out of the compiled code, but variables only referenced in the |
| 32 | * assertion won't trigger compiler warnings about being unused. |
| 33 | * - It is safe to use with a dangling-else: `if (x) SDL_assert(y); else |
| 34 | * do_something();` |
| 35 | * - It works the same everywhere, instead of counting on various platforms' |
| 36 | * compiler and C runtime to behave. |
| 37 | * - It provides multiple levels of assertion (SDL_assert, SDL_assert_release, |
| 38 | * SDL_assert_paranoid) instead of a single all-or-nothing option. |
| 39 | * - It offers a variety of responses when an assertion fails (retry, trigger |
| 40 | * the debugger, abort the program, ignore the failure once, ignore it for |
| 41 | * the rest of the program's run). |
| 42 | * - It tries to show the user a dialog by default, if possible, but the app |
| 43 | * can provide a callback to handle assertion failures however they like. |
| 44 | * - It lets failed assertions be retried. Perhaps you had a network failure |
| 45 | * and just want to retry the test after plugging your network cable back |
| 46 | * in? You can. |
| 47 | * - It lets the user ignore an assertion failure, if there's a harmless |
| 48 | * problem that one can continue past. |
| 49 | * - It lets the user mark an assertion as ignored for the rest of the |
| 50 | * program's run; if there's a harmless problem that keeps popping up. |
| 51 | * - It provides statistics and data on all failed assertions to the app. |
| 52 | * - It allows the default assertion handler to be controlled with environment |
| 53 | * variables, in case an automated script needs to control it. |
| 54 | * - It can be used as an aid to Clang's static analysis; it will treat SDL |
| 55 | * assertions as universally true (under the assumption that you are serious |
| 56 | * about the asserted claims and that your debug builds will detect when |
| 57 | * these claims were wrong). This can help the analyzer avoid false |
| 58 | * positives. |
| 59 | * |
| 60 | * To use it: compile a debug build and just sprinkle around tests to check |
| 61 | * your code! |
| 62 | */ |
| 63 | |
| 64 | #ifndef SDL_assert_h_ |
| 65 | #define SDL_assert_h_ |
| 66 | |
| 67 | #include <SDL3/SDL_stdinc.h> |
| 68 | |
| 69 | #include <SDL3/SDL_begin_code.h> |
| 70 | /* Set up for C function definitions, even when using C++ */ |
| 71 | #ifdef __cplusplus |
| 72 | extern "C" { |
| 73 | #endif |
| 74 | |
| 75 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION |
| 76 | |
| 77 | /** |
| 78 | * The level of assertion aggressiveness. |
| 79 | * |
| 80 | * This value changes depending on compiler options and other preprocessor |
| 81 | * defines. |
| 82 | * |
| 83 | * It is currently one of the following values, but future SDL releases might |
| 84 | * add more: |
| 85 | * |
| 86 | * - 0: All SDL assertion macros are disabled. |
| 87 | * - 1: Release settings: SDL_assert disabled, SDL_assert_release enabled. |
| 88 | * - 2: Debug settings: SDL_assert and SDL_assert_release enabled. |
| 89 | * - 3: Paranoid settings: All SDL assertion macros enabled, including |
| 90 | * SDL_assert_paranoid. |
| 91 | * |
| 92 | * \since This macro is available since SDL 3.2.0. |
| 93 | */ |
| 94 | #define SDL_ASSERT_LEVEL SomeNumberBasedOnVariousFactors |
| 95 | |
| 96 | #elif !defined(SDL_ASSERT_LEVEL) |
| 97 | #ifdef SDL_DEFAULT_ASSERT_LEVEL |
| 98 | #define SDL_ASSERT_LEVEL SDL_DEFAULT_ASSERT_LEVEL |
| 99 | #elif defined(_DEBUG) || defined(DEBUG) || \ |
| 100 | (defined(__GNUC__) && !defined(__OPTIMIZE__)) |
| 101 | #define SDL_ASSERT_LEVEL 2 |
| 102 | #else |
| 103 | #define SDL_ASSERT_LEVEL 1 |
| 104 | #endif |
| 105 | #endif |
| 106 | |
| 107 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION |
| 108 | |
| 109 | /** |
| 110 | * Attempt to tell an attached debugger to pause. |
| 111 | * |
| 112 | * This allows an app to programmatically halt ("break") the debugger as if it |
| 113 | * had hit a breakpoint, allowing the developer to examine program state, etc. |
| 114 | * |
| 115 | * This is a macro--not a function--so that the debugger breaks on the source |
| 116 | * code line that used SDL_TriggerBreakpoint and not in some random guts of |
| 117 | * SDL. SDL_assert uses this macro for the same reason. |
| 118 | * |
| 119 | * If the program is not running under a debugger, SDL_TriggerBreakpoint will |
| 120 | * likely terminate the app, possibly without warning. If the current platform |
| 121 | * isn't supported, this macro is left undefined. |
| 122 | * |
| 123 | * \threadsafety It is safe to call this macro from any thread. |
| 124 | * |
| 125 | * \since This macro is available since SDL 3.2.0. |
| 126 | */ |
| 127 | #define SDL_TriggerBreakpoint() TriggerABreakpointInAPlatformSpecificManner |
| 128 | |
| 129 | #elif defined(_MSC_VER) && _MSC_VER >= 1310 |
| 130 | /* Don't include intrin.h here because it contains C++ code */ |
| 131 | extern void __cdecl __debugbreak(void); |
| 132 | #define SDL_TriggerBreakpoint() __debugbreak() |
| 133 | #elif defined(_MSC_VER) && defined(_M_IX86) |
| 134 | #define SDL_TriggerBreakpoint() { _asm { int 0x03 } } |
| 135 | #elif defined(ANDROID) |
| 136 | #include <assert.h> |
| 137 | #define SDL_TriggerBreakpoint() assert(0) |
| 138 | #elif SDL_HAS_BUILTIN(__builtin_debugtrap) |
| 139 | #define SDL_TriggerBreakpoint() __builtin_debugtrap() |
| 140 | #elif SDL_HAS_BUILTIN(__builtin_trap) |
| 141 | #define SDL_TriggerBreakpoint() __builtin_trap() |
| 142 | #elif (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) |
| 143 | #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" ) |
| 144 | #elif (defined(__GNUC__) || defined(__clang__)) && defined(__riscv) |
| 145 | #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "ebreak\n\t" ) |
| 146 | #elif ( defined(SDL_PLATFORM_APPLE) && (defined(__arm64__) || defined(__aarch64__)) ) /* this might work on other ARM targets, but this is a known quantity... */ |
| 147 | #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" ) |
| 148 | #elif defined(SDL_PLATFORM_APPLE) && defined(__arm__) |
| 149 | #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "bkpt #22\n\t" ) |
| 150 | #elif defined(_WIN32) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__arm64__) || defined(__aarch64__)) ) |
| 151 | #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #0xF000\n\t" ) |
| 152 | #elif defined(__GNUC__) || defined(__clang__) |
| 153 | #define SDL_TriggerBreakpoint() __builtin_trap() /* older gcc may not support SDL_HAS_BUILTIN(__builtin_trap) above */ |
| 154 | #elif defined(__386__) && defined(__WATCOMC__) |
| 155 | #define SDL_TriggerBreakpoint() { _asm { int 0x03 } } |
| 156 | #elif defined(HAVE_SIGNAL_H) && !defined(__WATCOMC__) |
| 157 | #include <signal.h> |
| 158 | #define SDL_TriggerBreakpoint() raise(SIGTRAP) |
| 159 | #else |
| 160 | /* SDL_TriggerBreakpoint is intentionally left undefined on unknown platforms. */ |
| 161 | #endif |
| 162 | |
| 163 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION |
| 164 | |
| 165 | /** |
| 166 | * A macro that reports the current function being compiled. |
| 167 | * |
| 168 | * If SDL can't figure how the compiler reports this, it will use "???". |
| 169 | * |
| 170 | * \since This macro is available since SDL 3.2.0. |
| 171 | */ |
| 172 | #define SDL_FUNCTION __FUNCTION__ |
| 173 | |
| 174 | #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */ |
| 175 | # define SDL_FUNCTION __func__ |
| 176 | #elif ((defined(__GNUC__) && (__GNUC__ >= 2)) || defined(_MSC_VER) || defined (__WATCOMC__)) |
| 177 | # define SDL_FUNCTION __FUNCTION__ |
| 178 | #else |
| 179 | # define SDL_FUNCTION "???" |
| 180 | #endif |
| 181 | |
| 182 | /** |
| 183 | * A macro that reports the current file being compiled. |
| 184 | * |
| 185 | * \since This macro is available since SDL 3.2.0. |
| 186 | */ |
| 187 | #define SDL_FILE __FILE__ |
| 188 | |
| 189 | /** |
| 190 | * A macro that reports the current line number of the file being compiled. |
| 191 | * |
| 192 | * \since This macro is available since SDL 3.2.0. |
| 193 | */ |
| 194 | #define SDL_LINE __LINE__ |
| 195 | |
| 196 | /* |
| 197 | sizeof (x) makes the compiler still parse the expression even without |
| 198 | assertions enabled, so the code is always checked at compile time, but |
| 199 | doesn't actually generate code for it, so there are no side effects or |
| 200 | expensive checks at run time, just the constant size of what x WOULD be, |
| 201 | which presumably gets optimized out as unused. |
| 202 | This also solves the problem of... |
| 203 | |
| 204 | int somevalue = blah(); |
| 205 | SDL_assert(somevalue == 1); |
| 206 | |
| 207 | ...which would cause compiles to complain that somevalue is unused if we |
| 208 | disable assertions. |
| 209 | */ |
| 210 | |
| 211 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION |
| 212 | |
| 213 | /** |
| 214 | * A macro for wrapping code in `do {} while (0);` without compiler warnings. |
| 215 | * |
| 216 | * Visual Studio with really aggressive warnings enabled needs this to avoid |
| 217 | * compiler complaints. |
| 218 | * |
| 219 | * the `do {} while (0);` trick is useful for wrapping code in a macro that |
| 220 | * may or may not be a single statement, to avoid various C language |
| 221 | * accidents. |
| 222 | * |
| 223 | * To use: |
| 224 | * |
| 225 | * ```c |
| 226 | * do { SomethingOnce(); } while (SDL_NULL_WHILE_LOOP_CONDITION (0)); |
| 227 | * ``` |
| 228 | * |
| 229 | * \since This macro is available since SDL 3.2.0. |
| 230 | */ |
| 231 | #define SDL_NULL_WHILE_LOOP_CONDITION (0) |
| 232 | |
| 233 | #elif defined(_MSC_VER) /* Avoid /W4 warnings. */ |
| 234 | /* "while (0,0)" fools Microsoft's compiler's /W4 warning level into thinking |
| 235 | this condition isn't constant. And looks like an owl's face! */ |
| 236 | #define SDL_NULL_WHILE_LOOP_CONDITION (0,0) |
| 237 | #else |
| 238 | #define SDL_NULL_WHILE_LOOP_CONDITION (0) |
| 239 | #endif |
| 240 | |
| 241 | /** |
| 242 | * The macro used when an assertion is disabled. |
| 243 | * |
| 244 | * This isn't for direct use by apps, but this is the code that is inserted |
| 245 | * when an SDL_assert is disabled (perhaps in a release build). |
| 246 | * |
| 247 | * The code does nothing, but wraps `condition` in a sizeof operator, which |
| 248 | * generates no code and has no side effects, but avoid compiler warnings |
| 249 | * about unused variables. |
| 250 | * |
| 251 | * \param condition the condition to assert (but not actually run here). |
| 252 | * |
| 253 | * \since This macro is available since SDL 3.2.0. |
| 254 | */ |
| 255 | #define SDL_disabled_assert(condition) \ |
| 256 | do { (void) sizeof ((condition)); } while (SDL_NULL_WHILE_LOOP_CONDITION) |
| 257 | |
| 258 | /** |
| 259 | * Possible outcomes from a triggered assertion. |
| 260 | * |
| 261 | * When an enabled assertion triggers, it may call the assertion handler |
| 262 | * (possibly one provided by the app via SDL_SetAssertionHandler), which will |
| 263 | * return one of these values, possibly after asking the user. |
| 264 | * |
| 265 | * Then SDL will respond based on this outcome (loop around to retry the |
| 266 | * condition, try to break in a debugger, kill the program, or ignore the |
| 267 | * problem). |
| 268 | * |
| 269 | * \since This enum is available since SDL 3.2.0. |
| 270 | */ |
| 271 | typedef enum SDL_AssertState |
| 272 | { |
| 273 | SDL_ASSERTION_RETRY, /**< Retry the assert immediately. */ |
| 274 | SDL_ASSERTION_BREAK, /**< Make the debugger trigger a breakpoint. */ |
| 275 | SDL_ASSERTION_ABORT, /**< Terminate the program. */ |
| 276 | SDL_ASSERTION_IGNORE, /**< Ignore the assert. */ |
| 277 | SDL_ASSERTION_ALWAYS_IGNORE /**< Ignore the assert from now on. */ |
| 278 | } SDL_AssertState; |
| 279 | |
| 280 | /** |
| 281 | * Information about an assertion failure. |
| 282 | * |
| 283 | * This structure is filled in with information about a triggered assertion, |
| 284 | * used by the assertion handler, then added to the assertion report. This is |
| 285 | * returned as a linked list from SDL_GetAssertionReport(). |
| 286 | * |
| 287 | * \since This struct is available since SDL 3.2.0. |
| 288 | */ |
| 289 | typedef struct SDL_AssertData |
| 290 | { |
| 291 | bool always_ignore; /**< true if app should always continue when assertion is triggered. */ |
| 292 | unsigned int trigger_count; /**< Number of times this assertion has been triggered. */ |
| 293 | const char *condition; /**< A string of this assert's test code. */ |
| 294 | const char *filename; /**< The source file where this assert lives. */ |
| 295 | int linenum; /**< The line in `filename` where this assert lives. */ |
| 296 | const char *function; /**< The name of the function where this assert lives. */ |
| 297 | const struct SDL_AssertData *next; /**< next item in the linked list. */ |
| 298 | } SDL_AssertData; |
| 299 | |
| 300 | /** |
| 301 | * Never call this directly. |
| 302 | * |
| 303 | * Use the SDL_assert macros instead. |
| 304 | * |
| 305 | * \param data assert data structure. |
| 306 | * \param func function name. |
| 307 | * \param file file name. |
| 308 | * \param line line number. |
| 309 | * \returns assert state. |
| 310 | * |
| 311 | * \threadsafety It is safe to call this function from any thread. |
| 312 | * |
| 313 | * \since This function is available since SDL 3.2.0. |
| 314 | */ |
| 315 | extern SDL_DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *data, |
| 316 | const char *func, |
| 317 | const char *file, int line) SDL_ANALYZER_NORETURN; |
| 318 | |
| 319 | |
| 320 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION |
| 321 | |
| 322 | /** |
| 323 | * The macro used when an assertion triggers a breakpoint. |
| 324 | * |
| 325 | * This isn't for direct use by apps; use SDL_assert or SDL_TriggerBreakpoint |
| 326 | * instead. |
| 327 | * |
| 328 | * \since This macro is available since SDL 3.2.0. |
| 329 | */ |
| 330 | #define SDL_AssertBreakpoint() SDL_TriggerBreakpoint() |
| 331 | |
| 332 | #elif !defined(SDL_AssertBreakpoint) |
| 333 | # if defined(ANDROID) && defined(assert) |
| 334 | /* Define this as empty in case assert() is defined as SDL_assert */ |
| 335 | # define SDL_AssertBreakpoint() |
| 336 | # else |
| 337 | # define SDL_AssertBreakpoint() SDL_TriggerBreakpoint() |
| 338 | # endif |
| 339 | #endif /* !SDL_AssertBreakpoint */ |
| 340 | |
| 341 | /** |
| 342 | * The macro used when an assertion is enabled. |
| 343 | * |
| 344 | * This isn't for direct use by apps, but this is the code that is inserted |
| 345 | * when an SDL_assert is enabled. |
| 346 | * |
| 347 | * The `do {} while(0)` avoids dangling else problems: |
| 348 | * |
| 349 | * ```c |
| 350 | * if (x) SDL_assert(y); else blah(); |
| 351 | * ``` |
| 352 | * |
| 353 | * ... without the do/while, the "else" could attach to this macro's "if". We |
| 354 | * try to handle just the minimum we need here in a macro...the loop, the |
| 355 | * static vars, and break points. The heavy lifting is handled in |
| 356 | * SDL_ReportAssertion(). |
| 357 | * |
| 358 | * \param condition the condition to assert. |
| 359 | * |
| 360 | * \since This macro is available since SDL 3.2.0. |
| 361 | */ |
| 362 | #define SDL_enabled_assert(condition) \ |
| 363 | do { \ |
| 364 | while ( !(condition) ) { \ |
| 365 | static struct SDL_AssertData sdl_assert_data = { 0, 0, #condition, 0, 0, 0, 0 }; \ |
| 366 | const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \ |
| 367 | if (sdl_assert_state == SDL_ASSERTION_RETRY) { \ |
| 368 | continue; /* go again. */ \ |
| 369 | } else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \ |
| 370 | SDL_AssertBreakpoint(); \ |
| 371 | } \ |
| 372 | break; /* not retrying. */ \ |
| 373 | } \ |
| 374 | } while (SDL_NULL_WHILE_LOOP_CONDITION) |
| 375 | |
| 376 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION |
| 377 | |
| 378 | /** |
| 379 | * An assertion test that is normally performed only in debug builds. |
| 380 | * |
| 381 | * This macro is enabled when the SDL_ASSERT_LEVEL is >= 2, otherwise it is |
| 382 | * disabled. This is meant to only do these tests in debug builds, so they can |
| 383 | * tend to be more expensive, and they are meant to bring everything to a halt |
| 384 | * when they fail, with the programmer there to assess the problem. |
| 385 | * |
| 386 | * In short: you can sprinkle these around liberally and assume they will |
| 387 | * evaporate out of the build when building for end-users. |
| 388 | * |
| 389 | * When assertions are disabled, this wraps `condition` in a `sizeof` |
| 390 | * operator, which means any function calls and side effects will not run, but |
| 391 | * the compiler will not complain about any otherwise-unused variables that |
| 392 | * are only referenced in the assertion. |
| 393 | * |
| 394 | * One can set the environment variable "SDL_ASSERT" to one of several strings |
| 395 | * ("abort", "break", "retry", "ignore", "always_ignore") to force a default |
| 396 | * behavior, which may be desirable for automation purposes. If your platform |
| 397 | * requires GUI interfaces to happen on the main thread but you're debugging |
| 398 | * an assertion in a background thread, it might be desirable to set this to |
| 399 | * "break" so that your debugger takes control as soon as assert is triggered, |
| 400 | * instead of risking a bad UI interaction (deadlock, etc) in the application. |
| 401 | * |
| 402 | * \param condition boolean value to test. |
| 403 | * |
| 404 | * \threadsafety It is safe to call this macro from any thread. |
| 405 | * |
| 406 | * \since This macro is available since SDL 3.2.0. |
| 407 | */ |
| 408 | #define SDL_assert(condition) if (assertion_enabled && (condition)) { trigger_assertion; } |
| 409 | |
| 410 | /** |
| 411 | * An assertion test that is performed even in release builds. |
| 412 | * |
| 413 | * This macro is enabled when the SDL_ASSERT_LEVEL is >= 1, otherwise it is |
| 414 | * disabled. This is meant to be for tests that are cheap to make and |
| 415 | * extremely unlikely to fail; generally it is frowned upon to have an |
| 416 | * assertion failure in a release build, so these assertions generally need to |
| 417 | * be of more than life-and-death importance if there's a chance they might |
| 418 | * trigger. You should almost always consider handling these cases more |
| 419 | * gracefully than an assert allows. |
| 420 | * |
| 421 | * When assertions are disabled, this wraps `condition` in a `sizeof` |
| 422 | * operator, which means any function calls and side effects will not run, but |
| 423 | * the compiler will not complain about any otherwise-unused variables that |
| 424 | * are only referenced in the assertion. |
| 425 | * |
| 426 | * One can set the environment variable "SDL_ASSERT" to one of several strings |
| 427 | * ("abort", "break", "retry", "ignore", "always_ignore") to force a default |
| 428 | * behavior, which may be desirable for automation purposes. If your platform |
| 429 | * requires GUI interfaces to happen on the main thread but you're debugging |
| 430 | * an assertion in a background thread, it might be desirable to set this to |
| 431 | * "break" so that your debugger takes control as soon as assert is triggered, |
| 432 | * instead of risking a bad UI interaction (deadlock, etc) in the application. |
| 433 | * * |
| 434 | * |
| 435 | * \param condition boolean value to test. |
| 436 | * |
| 437 | * \threadsafety It is safe to call this macro from any thread. |
| 438 | * |
| 439 | * \since This macro is available since SDL 3.2.0. |
| 440 | */ |
| 441 | #define SDL_assert_release(condition) SDL_disabled_assert(condition) |
| 442 | |
| 443 | /** |
| 444 | * An assertion test that is performed only when built with paranoid settings. |
| 445 | * |
| 446 | * This macro is enabled when the SDL_ASSERT_LEVEL is >= 3, otherwise it is |
| 447 | * disabled. This is a higher level than both release and debug, so these |
| 448 | * tests are meant to be expensive and only run when specifically looking for |
| 449 | * extremely unexpected failure cases in a special build. |
| 450 | * |
| 451 | * When assertions are disabled, this wraps `condition` in a `sizeof` |
| 452 | * operator, which means any function calls and side effects will not run, but |
| 453 | * the compiler will not complain about any otherwise-unused variables that |
| 454 | * are only referenced in the assertion. |
| 455 | * |
| 456 | * One can set the environment variable "SDL_ASSERT" to one of several strings |
| 457 | * ("abort", "break", "retry", "ignore", "always_ignore") to force a default |
| 458 | * behavior, which may be desirable for automation purposes. If your platform |
| 459 | * requires GUI interfaces to happen on the main thread but you're debugging |
| 460 | * an assertion in a background thread, it might be desirable to set this to |
| 461 | * "break" so that your debugger takes control as soon as assert is triggered, |
| 462 | * instead of risking a bad UI interaction (deadlock, etc) in the application. |
| 463 | * |
| 464 | * \param condition boolean value to test. |
| 465 | * |
| 466 | * \threadsafety It is safe to call this macro from any thread. |
| 467 | * |
| 468 | * \since This macro is available since SDL 3.2.0. |
| 469 | */ |
| 470 | #define SDL_assert_paranoid(condition) SDL_disabled_assert(condition) |
| 471 | |
| 472 | /* Enable various levels of assertions. */ |
| 473 | #elif SDL_ASSERT_LEVEL == 0 /* assertions disabled */ |
| 474 | # define SDL_assert(condition) SDL_disabled_assert(condition) |
| 475 | # define SDL_assert_release(condition) SDL_disabled_assert(condition) |
| 476 | # define SDL_assert_paranoid(condition) SDL_disabled_assert(condition) |
| 477 | #elif SDL_ASSERT_LEVEL == 1 /* release settings. */ |
| 478 | # define SDL_assert(condition) SDL_disabled_assert(condition) |
| 479 | # define SDL_assert_release(condition) SDL_enabled_assert(condition) |
| 480 | # define SDL_assert_paranoid(condition) SDL_disabled_assert(condition) |
| 481 | #elif SDL_ASSERT_LEVEL == 2 /* debug settings. */ |
| 482 | # define SDL_assert(condition) SDL_enabled_assert(condition) |
| 483 | # define SDL_assert_release(condition) SDL_enabled_assert(condition) |
| 484 | # define SDL_assert_paranoid(condition) SDL_disabled_assert(condition) |
| 485 | #elif SDL_ASSERT_LEVEL == 3 /* paranoid settings. */ |
| 486 | # define SDL_assert(condition) SDL_enabled_assert(condition) |
| 487 | # define SDL_assert_release(condition) SDL_enabled_assert(condition) |
| 488 | # define SDL_assert_paranoid(condition) SDL_enabled_assert(condition) |
| 489 | #else |
| 490 | # error Unknown assertion level. |
| 491 | #endif |
| 492 | |
| 493 | /** |
| 494 | * An assertion test that is always performed. |
| 495 | * |
| 496 | * This macro is always enabled no matter what SDL_ASSERT_LEVEL is set to. You |
| 497 | * almost never want to use this, as it could trigger on an end-user's system, |
| 498 | * crashing your program. |
| 499 | * |
| 500 | * One can set the environment variable "SDL_ASSERT" to one of several strings |
| 501 | * ("abort", "break", "retry", "ignore", "always_ignore") to force a default |
| 502 | * behavior, which may be desirable for automation purposes. If your platform |
| 503 | * requires GUI interfaces to happen on the main thread but you're debugging |
| 504 | * an assertion in a background thread, it might be desirable to set this to |
| 505 | * "break" so that your debugger takes control as soon as assert is triggered, |
| 506 | * instead of risking a bad UI interaction (deadlock, etc) in the application. |
| 507 | * |
| 508 | * \param condition boolean value to test. |
| 509 | * |
| 510 | * \threadsafety It is safe to call this macro from any thread. |
| 511 | * |
| 512 | * \since This macro is available since SDL 3.2.0. |
| 513 | */ |
| 514 | #define SDL_assert_always(condition) SDL_enabled_assert(condition) |
| 515 | |
| 516 | |
| 517 | /** |
| 518 | * A callback that fires when an SDL assertion fails. |
| 519 | * |
| 520 | * \param data a pointer to the SDL_AssertData structure corresponding to the |
| 521 | * current assertion. |
| 522 | * \param userdata what was passed as `userdata` to SDL_SetAssertionHandler(). |
| 523 | * \returns an SDL_AssertState value indicating how to handle the failure. |
| 524 | * |
| 525 | * \threadsafety This callback may be called from any thread that triggers an |
| 526 | * assert at any time. |
| 527 | * |
| 528 | * \since This datatype is available since SDL 3.2.0. |
| 529 | */ |
| 530 | typedef SDL_AssertState (SDLCALL *SDL_AssertionHandler)( |
| 531 | const SDL_AssertData *data, void *userdata); |
| 532 | |
| 533 | /** |
| 534 | * Set an application-defined assertion handler. |
| 535 | * |
| 536 | * This function allows an application to show its own assertion UI and/or |
| 537 | * force the response to an assertion failure. If the application doesn't |
| 538 | * provide this, SDL will try to do the right thing, popping up a |
| 539 | * system-specific GUI dialog, and probably minimizing any fullscreen windows. |
| 540 | * |
| 541 | * This callback may fire from any thread, but it runs wrapped in a mutex, so |
| 542 | * it will only fire from one thread at a time. |
| 543 | * |
| 544 | * This callback is NOT reset to SDL's internal handler upon SDL_Quit()! |
| 545 | * |
| 546 | * \param handler the SDL_AssertionHandler function to call when an assertion |
| 547 | * fails or NULL for the default handler. |
| 548 | * \param userdata a pointer that is passed to `handler`. |
| 549 | * |
| 550 | * \threadsafety It is safe to call this function from any thread. |
| 551 | * |
| 552 | * \since This function is available since SDL 3.2.0. |
| 553 | * |
| 554 | * \sa SDL_GetAssertionHandler |
| 555 | */ |
| 556 | extern SDL_DECLSPEC void SDLCALL SDL_SetAssertionHandler( |
| 557 | SDL_AssertionHandler handler, |
| 558 | void *userdata); |
| 559 | |
| 560 | /** |
| 561 | * Get the default assertion handler. |
| 562 | * |
| 563 | * This returns the function pointer that is called by default when an |
| 564 | * assertion is triggered. This is an internal function provided by SDL, that |
| 565 | * is used for assertions when SDL_SetAssertionHandler() hasn't been used to |
| 566 | * provide a different function. |
| 567 | * |
| 568 | * \returns the default SDL_AssertionHandler that is called when an assert |
| 569 | * triggers. |
| 570 | * |
| 571 | * \threadsafety It is safe to call this function from any thread. |
| 572 | * |
| 573 | * \since This function is available since SDL 3.2.0. |
| 574 | * |
| 575 | * \sa SDL_GetAssertionHandler |
| 576 | */ |
| 577 | extern SDL_DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetDefaultAssertionHandler(void); |
| 578 | |
| 579 | /** |
| 580 | * Get the current assertion handler. |
| 581 | * |
| 582 | * This returns the function pointer that is called when an assertion is |
| 583 | * triggered. This is either the value last passed to |
| 584 | * SDL_SetAssertionHandler(), or if no application-specified function is set, |
| 585 | * is equivalent to calling SDL_GetDefaultAssertionHandler(). |
| 586 | * |
| 587 | * The parameter `puserdata` is a pointer to a void*, which will store the |
| 588 | * "userdata" pointer that was passed to SDL_SetAssertionHandler(). This value |
| 589 | * will always be NULL for the default handler. If you don't care about this |
| 590 | * data, it is safe to pass a NULL pointer to this function to ignore it. |
| 591 | * |
| 592 | * \param puserdata pointer which is filled with the "userdata" pointer that |
| 593 | * was passed to SDL_SetAssertionHandler(). |
| 594 | * \returns the SDL_AssertionHandler that is called when an assert triggers. |
| 595 | * |
| 596 | * \threadsafety It is safe to call this function from any thread. |
| 597 | * |
| 598 | * \since This function is available since SDL 3.2.0. |
| 599 | * |
| 600 | * \sa SDL_SetAssertionHandler |
| 601 | */ |
| 602 | extern SDL_DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puserdata); |
| 603 | |
| 604 | /** |
| 605 | * Get a list of all assertion failures. |
| 606 | * |
| 607 | * This function gets all assertions triggered since the last call to |
| 608 | * SDL_ResetAssertionReport(), or the start of the program. |
| 609 | * |
| 610 | * The proper way to examine this data looks something like this: |
| 611 | * |
| 612 | * ```c |
| 613 | * const SDL_AssertData *item = SDL_GetAssertionReport(); |
| 614 | * while (item) { |
| 615 | * printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\\n", |
| 616 | * item->condition, item->function, item->filename, |
| 617 | * item->linenum, item->trigger_count, |
| 618 | * item->always_ignore ? "yes" : "no"); |
| 619 | * item = item->next; |
| 620 | * } |
| 621 | * ``` |
| 622 | * |
| 623 | * \returns a list of all failed assertions or NULL if the list is empty. This |
| 624 | * memory should not be modified or freed by the application. This |
| 625 | * pointer remains valid until the next call to SDL_Quit() or |
| 626 | * SDL_ResetAssertionReport(). |
| 627 | * |
| 628 | * \threadsafety This function is not thread safe. Other threads calling |
| 629 | * SDL_ResetAssertionReport() simultaneously, may render the |
| 630 | * returned pointer invalid. |
| 631 | * |
| 632 | * \since This function is available since SDL 3.2.0. |
| 633 | * |
| 634 | * \sa SDL_ResetAssertionReport |
| 635 | */ |
| 636 | extern SDL_DECLSPEC const SDL_AssertData * SDLCALL SDL_GetAssertionReport(void); |
| 637 | |
| 638 | /** |
| 639 | * Clear the list of all assertion failures. |
| 640 | * |
| 641 | * This function will clear the list of all assertions triggered up to that |
| 642 | * point. Immediately following this call, SDL_GetAssertionReport will return |
| 643 | * no items. In addition, any previously-triggered assertions will be reset to |
| 644 | * a trigger_count of zero, and their always_ignore state will be false. |
| 645 | * |
| 646 | * \threadsafety This function is not thread safe. Other threads triggering an |
| 647 | * assertion, or simultaneously calling this function may cause |
| 648 | * memory leaks or crashes. |
| 649 | * |
| 650 | * \since This function is available since SDL 3.2.0. |
| 651 | * |
| 652 | * \sa SDL_GetAssertionReport |
| 653 | */ |
| 654 | extern SDL_DECLSPEC void SDLCALL SDL_ResetAssertionReport(void); |
| 655 | |
| 656 | /* Ends C function definitions when using C++ */ |
| 657 | #ifdef __cplusplus |
| 658 | } |
| 659 | #endif |
| 660 | #include <SDL3/SDL_close_code.h> |
| 661 | |
| 662 | #endif /* SDL_assert_h_ */ |
| 663 | |