Mercurial > foo_out_sdl
comparison SDL3/SDL_assert.h @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 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(__MINGW32__) || (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 SDL_HAS_BUILTIN(__builtin_debugtrap) | |
| 136 #define SDL_TriggerBreakpoint() __builtin_debugtrap() | |
| 137 #elif SDL_HAS_BUILTIN(__builtin_trap) | |
| 138 #define SDL_TriggerBreakpoint() __builtin_trap() | |
| 139 #elif (defined(__GNUC__) || defined(__clang__) || defined(__TINYC__)) && (defined(__i386__) || defined(__x86_64__)) | |
| 140 #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" ) | |
| 141 #elif (defined(__GNUC__) || defined(__clang__)) && defined(__riscv) | |
| 142 #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "ebreak\n\t" ) | |
| 143 #elif ( defined(SDL_PLATFORM_APPLE) && (defined(__arm64__) || defined(__aarch64__)) ) /* this might work on other ARM targets, but this is a known quantity... */ | |
| 144 #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" ) | |
| 145 #elif defined(SDL_PLATFORM_APPLE) && defined(__arm__) | |
| 146 #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "bkpt #22\n\t" ) | |
| 147 #elif defined(_WIN32) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__arm64__) || defined(__aarch64__)) ) | |
| 148 #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #0xF000\n\t" ) | |
| 149 #elif defined(__GNUC__) || defined(__clang__) | |
| 150 #define SDL_TriggerBreakpoint() __builtin_trap() /* older gcc may not support SDL_HAS_BUILTIN(__builtin_trap) above */ | |
| 151 #elif defined(__386__) && defined(__WATCOMC__) | |
| 152 #define SDL_TriggerBreakpoint() { _asm { int 0x03 } } | |
| 153 #elif defined(HAVE_SIGNAL_H) && !defined(__WATCOMC__) | |
| 154 #include <signal.h> | |
| 155 #define SDL_TriggerBreakpoint() raise(SIGTRAP) | |
| 156 #else | |
| 157 /* SDL_TriggerBreakpoint is intentionally left undefined on unknown platforms. */ | |
| 158 #endif | |
| 159 | |
| 160 #ifdef SDL_WIKI_DOCUMENTATION_SECTION | |
| 161 | |
| 162 /** | |
| 163 * A macro that reports the current function being compiled. | |
| 164 * | |
| 165 * If SDL can't figure how the compiler reports this, it will use "???". | |
| 166 * | |
| 167 * \since This macro is available since SDL 3.2.0. | |
| 168 */ | |
| 169 #define SDL_FUNCTION __FUNCTION__ | |
| 170 | |
| 171 #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */ | |
| 172 # define SDL_FUNCTION __func__ | |
| 173 #elif ((defined(__GNUC__) && (__GNUC__ >= 2)) || defined(_MSC_VER) || defined (__WATCOMC__)) | |
| 174 # define SDL_FUNCTION __FUNCTION__ | |
| 175 #else | |
| 176 # define SDL_FUNCTION "???" | |
| 177 #endif | |
| 178 | |
| 179 #ifdef SDL_WIKI_DOCUMENTATION_SECTION | |
| 180 | |
| 181 /** | |
| 182 * A macro that reports the current file being compiled. | |
| 183 * | |
| 184 * This macro is only defined if it isn't already defined, so to override it | |
| 185 * (perhaps with something that doesn't provide path information at all, so | |
| 186 * build machine information doesn't leak into public binaries), apps can | |
| 187 * define this macro before including SDL.h or SDL_assert.h. | |
| 188 * | |
| 189 * \since This macro is available since SDL 3.2.0. | |
| 190 */ | |
| 191 #define SDL_FILE __FILE_NAME__ | |
| 192 | |
| 193 #elif !defined(SDL_FILE) | |
| 194 #ifdef __FILE_NAME__ | |
| 195 #define SDL_FILE __FILE_NAME__ | |
| 196 #else | |
| 197 #define SDL_FILE __FILE__ | |
| 198 #endif | |
| 199 #endif | |
| 200 | |
| 201 #ifdef SDL_WIKI_DOCUMENTATION_SECTION | |
| 202 | |
| 203 /** | |
| 204 * A macro that reports the current file being compiled, for use in | |
| 205 * assertions. | |
| 206 * | |
| 207 * This macro is only defined if it isn't already defined, so to override it | |
| 208 * (perhaps with something that doesn't provide path information at all, so | |
| 209 * build machine information doesn't leak into public binaries), apps can | |
| 210 * define this macro before including SDL_assert.h. For example, defining this | |
| 211 * to `""` will make sure no source path information is included in asserts. | |
| 212 * | |
| 213 * \since This macro is available since SDL 3.4.0. | |
| 214 */ | |
| 215 #define SDL_ASSERT_FILE SDL_FILE | |
| 216 | |
| 217 #elif !defined(SDL_ASSERT_FILE) | |
| 218 #define SDL_ASSERT_FILE SDL_FILE | |
| 219 #endif | |
| 220 | |
| 221 | |
| 222 /** | |
| 223 * A macro that reports the current line number of the file being compiled. | |
| 224 * | |
| 225 * \since This macro is available since SDL 3.2.0. | |
| 226 */ | |
| 227 #define SDL_LINE __LINE__ | |
| 228 | |
| 229 /* | |
| 230 sizeof (x) makes the compiler still parse the expression even without | |
| 231 assertions enabled, so the code is always checked at compile time, but | |
| 232 doesn't actually generate code for it, so there are no side effects or | |
| 233 expensive checks at run time, just the constant size of what x WOULD be, | |
| 234 which presumably gets optimized out as unused. | |
| 235 This also solves the problem of... | |
| 236 | |
| 237 int somevalue = blah(); | |
| 238 SDL_assert(somevalue == 1); | |
| 239 | |
| 240 ...which would cause compiles to complain that somevalue is unused if we | |
| 241 disable assertions. | |
| 242 */ | |
| 243 | |
| 244 #ifdef SDL_WIKI_DOCUMENTATION_SECTION | |
| 245 | |
| 246 /** | |
| 247 * A macro for wrapping code in `do {} while (0);` without compiler warnings. | |
| 248 * | |
| 249 * Visual Studio with really aggressive warnings enabled needs this to avoid | |
| 250 * compiler complaints. | |
| 251 * | |
| 252 * the `do {} while (0);` trick is useful for wrapping code in a macro that | |
| 253 * may or may not be a single statement, to avoid various C language | |
| 254 * accidents. | |
| 255 * | |
| 256 * To use: | |
| 257 * | |
| 258 * ```c | |
| 259 * do { SomethingOnce(); } while (SDL_NULL_WHILE_LOOP_CONDITION (0)); | |
| 260 * ``` | |
| 261 * | |
| 262 * \since This macro is available since SDL 3.2.0. | |
| 263 */ | |
| 264 #define SDL_NULL_WHILE_LOOP_CONDITION (0) | |
| 265 | |
| 266 #elif defined(_MSC_VER) /* Avoid /W4 warnings. */ | |
| 267 /* "while (0,0)" fools Microsoft's compiler's /W4 warning level into thinking | |
| 268 this condition isn't constant. And looks like an owl's face! */ | |
| 269 #define SDL_NULL_WHILE_LOOP_CONDITION (0,0) | |
| 270 #else | |
| 271 #define SDL_NULL_WHILE_LOOP_CONDITION (0) | |
| 272 #endif | |
| 273 | |
| 274 /** | |
| 275 * The macro used when an assertion is disabled. | |
| 276 * | |
| 277 * This isn't for direct use by apps, but this is the code that is inserted | |
| 278 * when an SDL_assert is disabled (perhaps in a release build). | |
| 279 * | |
| 280 * The code does nothing, but wraps `condition` in a sizeof operator, which | |
| 281 * generates no code and has no side effects, but avoid compiler warnings | |
| 282 * about unused variables. | |
| 283 * | |
| 284 * \param condition the condition to assert (but not actually run here). | |
| 285 * | |
| 286 * \since This macro is available since SDL 3.2.0. | |
| 287 */ | |
| 288 #define SDL_disabled_assert(condition) \ | |
| 289 do { (void) sizeof ((condition)); } while (SDL_NULL_WHILE_LOOP_CONDITION) | |
| 290 | |
| 291 /** | |
| 292 * Possible outcomes from a triggered assertion. | |
| 293 * | |
| 294 * When an enabled assertion triggers, it may call the assertion handler | |
| 295 * (possibly one provided by the app via SDL_SetAssertionHandler), which will | |
| 296 * return one of these values, possibly after asking the user. | |
| 297 * | |
| 298 * Then SDL will respond based on this outcome (loop around to retry the | |
| 299 * condition, try to break in a debugger, kill the program, or ignore the | |
| 300 * problem). | |
| 301 * | |
| 302 * \since This enum is available since SDL 3.2.0. | |
| 303 */ | |
| 304 typedef enum SDL_AssertState | |
| 305 { | |
| 306 SDL_ASSERTION_RETRY, /**< Retry the assert immediately. */ | |
| 307 SDL_ASSERTION_BREAK, /**< Make the debugger trigger a breakpoint. */ | |
| 308 SDL_ASSERTION_ABORT, /**< Terminate the program. */ | |
| 309 SDL_ASSERTION_IGNORE, /**< Ignore the assert. */ | |
| 310 SDL_ASSERTION_ALWAYS_IGNORE /**< Ignore the assert from now on. */ | |
| 311 } SDL_AssertState; | |
| 312 | |
| 313 /** | |
| 314 * Information about an assertion failure. | |
| 315 * | |
| 316 * This structure is filled in with information about a triggered assertion, | |
| 317 * used by the assertion handler, then added to the assertion report. This is | |
| 318 * returned as a linked list from SDL_GetAssertionReport(). | |
| 319 * | |
| 320 * \since This struct is available since SDL 3.2.0. | |
| 321 */ | |
| 322 typedef struct SDL_AssertData | |
| 323 { | |
| 324 bool always_ignore; /**< true if app should always continue when assertion is triggered. */ | |
| 325 unsigned int trigger_count; /**< Number of times this assertion has been triggered. */ | |
| 326 const char *condition; /**< A string of this assert's test code. */ | |
| 327 const char *filename; /**< The source file where this assert lives. */ | |
| 328 int linenum; /**< The line in `filename` where this assert lives. */ | |
| 329 const char *function; /**< The name of the function where this assert lives. */ | |
| 330 const struct SDL_AssertData *next; /**< next item in the linked list. */ | |
| 331 } SDL_AssertData; | |
| 332 | |
| 333 /** | |
| 334 * Never call this directly. | |
| 335 * | |
| 336 * Use the SDL_assert macros instead. | |
| 337 * | |
| 338 * \param data assert data structure. | |
| 339 * \param func function name. | |
| 340 * \param file file name. | |
| 341 * \param line line number. | |
| 342 * \returns assert state. | |
| 343 * | |
| 344 * \threadsafety It is safe to call this function from any thread. | |
| 345 * | |
| 346 * \since This function is available since SDL 3.2.0. | |
| 347 */ | |
| 348 extern SDL_DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *data, | |
| 349 const char *func, | |
| 350 const char *file, int line) SDL_ANALYZER_NORETURN; | |
| 351 | |
| 352 | |
| 353 #ifdef SDL_WIKI_DOCUMENTATION_SECTION | |
| 354 | |
| 355 /** | |
| 356 * The macro used when an assertion triggers a breakpoint. | |
| 357 * | |
| 358 * This isn't for direct use by apps; use SDL_assert or SDL_TriggerBreakpoint | |
| 359 * instead. | |
| 360 * | |
| 361 * \since This macro is available since SDL 3.2.0. | |
| 362 */ | |
| 363 #define SDL_AssertBreakpoint() SDL_TriggerBreakpoint() | |
| 364 | |
| 365 #elif !defined(SDL_AssertBreakpoint) | |
| 366 # if defined(ANDROID) && defined(assert) | |
| 367 /* Define this as empty in case assert() is defined as SDL_assert */ | |
| 368 # define SDL_AssertBreakpoint() | |
| 369 # else | |
| 370 # define SDL_AssertBreakpoint() SDL_TriggerBreakpoint() | |
| 371 # endif | |
| 372 #endif /* !SDL_AssertBreakpoint */ | |
| 373 | |
| 374 /** | |
| 375 * The macro used when an assertion is enabled. | |
| 376 * | |
| 377 * This isn't for direct use by apps, but this is the code that is inserted | |
| 378 * when an SDL_assert is enabled. | |
| 379 * | |
| 380 * The `do {} while(0)` avoids dangling else problems: | |
| 381 * | |
| 382 * ```c | |
| 383 * if (x) SDL_assert(y); else blah(); | |
| 384 * ``` | |
| 385 * | |
| 386 * ... without the do/while, the "else" could attach to this macro's "if". We | |
| 387 * try to handle just the minimum we need here in a macro...the loop, the | |
| 388 * static vars, and break points. The heavy lifting is handled in | |
| 389 * SDL_ReportAssertion(). | |
| 390 * | |
| 391 * \param condition the condition to assert. | |
| 392 * | |
| 393 * \since This macro is available since SDL 3.2.0. | |
| 394 */ | |
| 395 #define SDL_enabled_assert(condition) \ | |
| 396 do { \ | |
| 397 while ( !(condition) ) { \ | |
| 398 static struct SDL_AssertData sdl_assert_data = { false, 0, #condition, NULL, 0, NULL, NULL }; \ | |
| 399 const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_ASSERT_FILE, SDL_LINE); \ | |
| 400 if (sdl_assert_state == SDL_ASSERTION_RETRY) { \ | |
| 401 continue; /* go again. */ \ | |
| 402 } else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \ | |
| 403 SDL_AssertBreakpoint(); \ | |
| 404 } \ | |
| 405 break; /* not retrying. */ \ | |
| 406 } \ | |
| 407 } while (SDL_NULL_WHILE_LOOP_CONDITION) | |
| 408 | |
| 409 #ifdef SDL_WIKI_DOCUMENTATION_SECTION | |
| 410 | |
| 411 /** | |
| 412 * An assertion test that is normally performed only in debug builds. | |
| 413 * | |
| 414 * This macro is enabled when the SDL_ASSERT_LEVEL is >= 2, otherwise it is | |
| 415 * disabled. This is meant to only do these tests in debug builds, so they can | |
| 416 * tend to be more expensive, and they are meant to bring everything to a halt | |
| 417 * when they fail, with the programmer there to assess the problem. | |
| 418 * | |
| 419 * In short: you can sprinkle these around liberally and assume they will | |
| 420 * evaporate out of the build when building for end-users. | |
| 421 * | |
| 422 * When assertions are disabled, this wraps `condition` in a `sizeof` | |
| 423 * operator, which means any function calls and side effects will not run, but | |
| 424 * the compiler will not complain about any otherwise-unused variables that | |
| 425 * are only referenced in the assertion. | |
| 426 * | |
| 427 * One can set the environment variable "SDL_ASSERT" to one of several strings | |
| 428 * ("abort", "break", "retry", "ignore", "always_ignore") to force a default | |
| 429 * behavior, which may be desirable for automation purposes. If your platform | |
| 430 * requires GUI interfaces to happen on the main thread but you're debugging | |
| 431 * an assertion in a background thread, it might be desirable to set this to | |
| 432 * "break" so that your debugger takes control as soon as assert is triggered, | |
| 433 * instead of risking a bad UI interaction (deadlock, etc) in the application. | |
| 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(condition) if (assertion_enabled && (condition)) { trigger_assertion; } | |
| 442 | |
| 443 /** | |
| 444 * An assertion test that is performed even in release builds. | |
| 445 * | |
| 446 * This macro is enabled when the SDL_ASSERT_LEVEL is >= 1, otherwise it is | |
| 447 * disabled. This is meant to be for tests that are cheap to make and | |
| 448 * extremely unlikely to fail; generally it is frowned upon to have an | |
| 449 * assertion failure in a release build, so these assertions generally need to | |
| 450 * be of more than life-and-death importance if there's a chance they might | |
| 451 * trigger. You should almost always consider handling these cases more | |
| 452 * gracefully than an assert allows. | |
| 453 * | |
| 454 * When assertions are disabled, this wraps `condition` in a `sizeof` | |
| 455 * operator, which means any function calls and side effects will not run, but | |
| 456 * the compiler will not complain about any otherwise-unused variables that | |
| 457 * are only referenced in the assertion. | |
| 458 * | |
| 459 * One can set the environment variable "SDL_ASSERT" to one of several strings | |
| 460 * ("abort", "break", "retry", "ignore", "always_ignore") to force a default | |
| 461 * behavior, which may be desirable for automation purposes. If your platform | |
| 462 * requires GUI interfaces to happen on the main thread but you're debugging | |
| 463 * an assertion in a background thread, it might be desirable to set this to | |
| 464 * "break" so that your debugger takes control as soon as assert is triggered, | |
| 465 * instead of risking a bad UI interaction (deadlock, etc) in the application. | |
| 466 * * | |
| 467 * | |
| 468 * \param condition boolean value to test. | |
| 469 * | |
| 470 * \threadsafety It is safe to call this macro from any thread. | |
| 471 * | |
| 472 * \since This macro is available since SDL 3.2.0. | |
| 473 */ | |
| 474 #define SDL_assert_release(condition) SDL_disabled_assert(condition) | |
| 475 | |
| 476 /** | |
| 477 * An assertion test that is performed only when built with paranoid settings. | |
| 478 * | |
| 479 * This macro is enabled when the SDL_ASSERT_LEVEL is >= 3, otherwise it is | |
| 480 * disabled. This is a higher level than both release and debug, so these | |
| 481 * tests are meant to be expensive and only run when specifically looking for | |
| 482 * extremely unexpected failure cases in a special build. | |
| 483 * | |
| 484 * When assertions are disabled, this wraps `condition` in a `sizeof` | |
| 485 * operator, which means any function calls and side effects will not run, but | |
| 486 * the compiler will not complain about any otherwise-unused variables that | |
| 487 * are only referenced in the assertion. | |
| 488 * | |
| 489 * One can set the environment variable "SDL_ASSERT" to one of several strings | |
| 490 * ("abort", "break", "retry", "ignore", "always_ignore") to force a default | |
| 491 * behavior, which may be desirable for automation purposes. If your platform | |
| 492 * requires GUI interfaces to happen on the main thread but you're debugging | |
| 493 * an assertion in a background thread, it might be desirable to set this to | |
| 494 * "break" so that your debugger takes control as soon as assert is triggered, | |
| 495 * instead of risking a bad UI interaction (deadlock, etc) in the application. | |
| 496 * | |
| 497 * \param condition boolean value to test. | |
| 498 * | |
| 499 * \threadsafety It is safe to call this macro from any thread. | |
| 500 * | |
| 501 * \since This macro is available since SDL 3.2.0. | |
| 502 */ | |
| 503 #define SDL_assert_paranoid(condition) SDL_disabled_assert(condition) | |
| 504 | |
| 505 /* Enable various levels of assertions. */ | |
| 506 #elif SDL_ASSERT_LEVEL == 0 /* assertions disabled */ | |
| 507 # define SDL_assert(condition) SDL_disabled_assert(condition) | |
| 508 # define SDL_assert_release(condition) SDL_disabled_assert(condition) | |
| 509 # define SDL_assert_paranoid(condition) SDL_disabled_assert(condition) | |
| 510 #elif SDL_ASSERT_LEVEL == 1 /* release settings. */ | |
| 511 # define SDL_assert(condition) SDL_disabled_assert(condition) | |
| 512 # define SDL_assert_release(condition) SDL_enabled_assert(condition) | |
| 513 # define SDL_assert_paranoid(condition) SDL_disabled_assert(condition) | |
| 514 #elif SDL_ASSERT_LEVEL == 2 /* debug settings. */ | |
| 515 # define SDL_assert(condition) SDL_enabled_assert(condition) | |
| 516 # define SDL_assert_release(condition) SDL_enabled_assert(condition) | |
| 517 # define SDL_assert_paranoid(condition) SDL_disabled_assert(condition) | |
| 518 #elif SDL_ASSERT_LEVEL == 3 /* paranoid settings. */ | |
| 519 # define SDL_assert(condition) SDL_enabled_assert(condition) | |
| 520 # define SDL_assert_release(condition) SDL_enabled_assert(condition) | |
| 521 # define SDL_assert_paranoid(condition) SDL_enabled_assert(condition) | |
| 522 #else | |
| 523 # error Unknown assertion level. | |
| 524 #endif | |
| 525 | |
| 526 /** | |
| 527 * An assertion test that is always performed. | |
| 528 * | |
| 529 * This macro is always enabled no matter what SDL_ASSERT_LEVEL is set to. You | |
| 530 * almost never want to use this, as it could trigger on an end-user's system, | |
| 531 * crashing your program. | |
| 532 * | |
| 533 * One can set the environment variable "SDL_ASSERT" to one of several strings | |
| 534 * ("abort", "break", "retry", "ignore", "always_ignore") to force a default | |
| 535 * behavior, which may be desirable for automation purposes. If your platform | |
| 536 * requires GUI interfaces to happen on the main thread but you're debugging | |
| 537 * an assertion in a background thread, it might be desirable to set this to | |
| 538 * "break" so that your debugger takes control as soon as assert is triggered, | |
| 539 * instead of risking a bad UI interaction (deadlock, etc) in the application. | |
| 540 * | |
| 541 * \param condition boolean value to test. | |
| 542 * | |
| 543 * \threadsafety It is safe to call this macro from any thread. | |
| 544 * | |
| 545 * \since This macro is available since SDL 3.2.0. | |
| 546 */ | |
| 547 #define SDL_assert_always(condition) SDL_enabled_assert(condition) | |
| 548 | |
| 549 | |
| 550 /** | |
| 551 * A callback that fires when an SDL assertion fails. | |
| 552 * | |
| 553 * \param data a pointer to the SDL_AssertData structure corresponding to the | |
| 554 * current assertion. | |
| 555 * \param userdata what was passed as `userdata` to SDL_SetAssertionHandler(). | |
| 556 * \returns an SDL_AssertState value indicating how to handle the failure. | |
| 557 * | |
| 558 * \threadsafety This callback may be called from any thread that triggers an | |
| 559 * assert at any time. | |
| 560 * | |
| 561 * \since This datatype is available since SDL 3.2.0. | |
| 562 */ | |
| 563 typedef SDL_AssertState (SDLCALL *SDL_AssertionHandler)( | |
| 564 const SDL_AssertData *data, void *userdata); | |
| 565 | |
| 566 /** | |
| 567 * Set an application-defined assertion handler. | |
| 568 * | |
| 569 * This function allows an application to show its own assertion UI and/or | |
| 570 * force the response to an assertion failure. If the application doesn't | |
| 571 * provide this, SDL will try to do the right thing, popping up a | |
| 572 * system-specific GUI dialog, and probably minimizing any fullscreen windows. | |
| 573 * | |
| 574 * This callback may fire from any thread, but it runs wrapped in a mutex, so | |
| 575 * it will only fire from one thread at a time. | |
| 576 * | |
| 577 * This callback is NOT reset to SDL's internal handler upon SDL_Quit()! | |
| 578 * | |
| 579 * \param handler the SDL_AssertionHandler function to call when an assertion | |
| 580 * fails or NULL for the default handler. | |
| 581 * \param userdata a pointer that is passed to `handler`. | |
| 582 * | |
| 583 * \threadsafety It is safe to call this function from any thread. | |
| 584 * | |
| 585 * \since This function is available since SDL 3.2.0. | |
| 586 * | |
| 587 * \sa SDL_GetAssertionHandler | |
| 588 */ | |
| 589 extern SDL_DECLSPEC void SDLCALL SDL_SetAssertionHandler( | |
| 590 SDL_AssertionHandler handler, | |
| 591 void *userdata); | |
| 592 | |
| 593 /** | |
| 594 * Get the default assertion handler. | |
| 595 * | |
| 596 * This returns the function pointer that is called by default when an | |
| 597 * assertion is triggered. This is an internal function provided by SDL, that | |
| 598 * is used for assertions when SDL_SetAssertionHandler() hasn't been used to | |
| 599 * provide a different function. | |
| 600 * | |
| 601 * \returns the default SDL_AssertionHandler that is called when an assert | |
| 602 * triggers. | |
| 603 * | |
| 604 * \threadsafety It is safe to call this function from any thread. | |
| 605 * | |
| 606 * \since This function is available since SDL 3.2.0. | |
| 607 * | |
| 608 * \sa SDL_GetAssertionHandler | |
| 609 */ | |
| 610 extern SDL_DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetDefaultAssertionHandler(void); | |
| 611 | |
| 612 /** | |
| 613 * Get the current assertion handler. | |
| 614 * | |
| 615 * This returns the function pointer that is called when an assertion is | |
| 616 * triggered. This is either the value last passed to | |
| 617 * SDL_SetAssertionHandler(), or if no application-specified function is set, | |
| 618 * is equivalent to calling SDL_GetDefaultAssertionHandler(). | |
| 619 * | |
| 620 * The parameter `puserdata` is a pointer to a void*, which will store the | |
| 621 * "userdata" pointer that was passed to SDL_SetAssertionHandler(). This value | |
| 622 * will always be NULL for the default handler. If you don't care about this | |
| 623 * data, it is safe to pass a NULL pointer to this function to ignore it. | |
| 624 * | |
| 625 * \param puserdata pointer which is filled with the "userdata" pointer that | |
| 626 * was passed to SDL_SetAssertionHandler(). | |
| 627 * \returns the SDL_AssertionHandler that is called when an assert triggers. | |
| 628 * | |
| 629 * \threadsafety It is safe to call this function from any thread. | |
| 630 * | |
| 631 * \since This function is available since SDL 3.2.0. | |
| 632 * | |
| 633 * \sa SDL_SetAssertionHandler | |
| 634 */ | |
| 635 extern SDL_DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puserdata); | |
| 636 | |
| 637 /** | |
| 638 * Get a list of all assertion failures. | |
| 639 * | |
| 640 * This function gets all assertions triggered since the last call to | |
| 641 * SDL_ResetAssertionReport(), or the start of the program. | |
| 642 * | |
| 643 * The proper way to examine this data looks something like this: | |
| 644 * | |
| 645 * ```c | |
| 646 * const SDL_AssertData *item = SDL_GetAssertionReport(); | |
| 647 * while (item) { | |
| 648 * printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\\n", | |
| 649 * item->condition, item->function, item->filename, | |
| 650 * item->linenum, item->trigger_count, | |
| 651 * item->always_ignore ? "yes" : "no"); | |
| 652 * item = item->next; | |
| 653 * } | |
| 654 * ``` | |
| 655 * | |
| 656 * \returns a list of all failed assertions or NULL if the list is empty. This | |
| 657 * memory should not be modified or freed by the application. This | |
| 658 * pointer remains valid until the next call to SDL_Quit() or | |
| 659 * SDL_ResetAssertionReport(). | |
| 660 * | |
| 661 * \threadsafety This function is not thread safe. Other threads calling | |
| 662 * SDL_ResetAssertionReport() simultaneously, may render the | |
| 663 * returned pointer invalid. | |
| 664 * | |
| 665 * \since This function is available since SDL 3.2.0. | |
| 666 * | |
| 667 * \sa SDL_ResetAssertionReport | |
| 668 */ | |
| 669 extern SDL_DECLSPEC const SDL_AssertData * SDLCALL SDL_GetAssertionReport(void); | |
| 670 | |
| 671 /** | |
| 672 * Clear the list of all assertion failures. | |
| 673 * | |
| 674 * This function will clear the list of all assertions triggered up to that | |
| 675 * point. Immediately following this call, SDL_GetAssertionReport will return | |
| 676 * no items. In addition, any previously-triggered assertions will be reset to | |
| 677 * a trigger_count of zero, and their always_ignore state will be false. | |
| 678 * | |
| 679 * \threadsafety This function is not thread safe. Other threads triggering an | |
| 680 * assertion, or simultaneously calling this function may cause | |
| 681 * memory leaks or crashes. | |
| 682 * | |
| 683 * \since This function is available since SDL 3.2.0. | |
| 684 * | |
| 685 * \sa SDL_GetAssertionReport | |
| 686 */ | |
| 687 extern SDL_DECLSPEC void SDLCALL SDL_ResetAssertionReport(void); | |
| 688 | |
| 689 /* Ends C function definitions when using C++ */ | |
| 690 #ifdef __cplusplus | |
| 691 } | |
| 692 #endif | |
| 693 #include <SDL3/SDL_close_code.h> | |
| 694 | |
| 695 #endif /* SDL_assert_h_ */ |
