mirror of
https://github.com/joel16/SDL2.git
synced 2025-03-04 17:39:32 +00:00
Clean up assertion API for public use.
--HG-- extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%404421
This commit is contained in:
parent
281945aa84
commit
c9bab7f01e
@ -109,7 +109,7 @@ typedef struct SDL_assert_data
|
||||
const char *filename;
|
||||
int linenum;
|
||||
const char *function;
|
||||
struct SDL_assert_data *next;
|
||||
const struct SDL_assert_data *next;
|
||||
} SDL_assert_data;
|
||||
|
||||
/* Never call this directly. Use the SDL_assert* macros. */
|
||||
@ -166,6 +166,68 @@ extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *,
|
||||
# error Unknown assertion level.
|
||||
#endif
|
||||
|
||||
|
||||
typedef SDL_assert_state (SDLCALL *SDL_AssertionHandler)(
|
||||
const SDL_assert_data *, void *userdata);
|
||||
|
||||
/**
|
||||
* \brief Set an application-defined assertion handler.
|
||||
*
|
||||
* This allows an app to show its own assertion UI and/or force the
|
||||
* response to an assertion failure. If the app 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.
|
||||
*
|
||||
* Setting the callback to NULL restores SDL's original internal handler.
|
||||
*
|
||||
* This callback is NOT reset to SDL's internal handler upon SDL_Quit()!
|
||||
*
|
||||
* \return SDL_assert_state value of how to handle the assertion failure.
|
||||
*
|
||||
* \param handler Callback function, called when an assertion fails.
|
||||
* \param userdata A pointer passed to the callback as-is.
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_SetAssertionHandler(
|
||||
SDL_AssertionHandler handler,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* \brief Get a list of all assertion failures.
|
||||
*
|
||||
* Get all assertions triggered since last call to SDL_ResetAssertionReport(),
|
||||
* or the start of the program.
|
||||
*
|
||||
* The proper way to examine this data looks something like this:
|
||||
*
|
||||
* <code>
|
||||
* const SDL_assert_data *item = SDL_GetAssertionReport();
|
||||
* while (item->condition) {
|
||||
* printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n",
|
||||
* item->condition, item->function, item->filename,
|
||||
* item->linenum, item->trigger_count,
|
||||
* item->always_ignore ? "yes" : "no");
|
||||
* item = item->next;
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* \return List of all assertions. This never returns NULL,
|
||||
* even if there are no items.
|
||||
* \sa SDL_ResetAssertionReport
|
||||
*/
|
||||
extern DECLSPEC const SDL_assert_data * SDLCALL SDL_GetAssertionReport(void);
|
||||
|
||||
/**
|
||||
* \brief Reset the list of all assertion failures.
|
||||
*
|
||||
* Reset list of all assertions triggered.
|
||||
*
|
||||
* \sa SDL_GetAssertionReport
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_ResetAssertionReport(void);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
|
@ -23,8 +23,6 @@
|
||||
#include "SDL.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#if (SDL_ASSERT_LEVEL > 0)
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <windows.h>
|
||||
@ -34,13 +32,19 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* We can keep all triggered assertions in a singly-linked list so we can
|
||||
static SDL_assert_state
|
||||
SDL_PromptAssertion(const SDL_assert_data *data, void *userdata);
|
||||
|
||||
/*
|
||||
* We keep all triggered assertions in a singly-linked list so we can
|
||||
* generate a report later.
|
||||
*/
|
||||
#if !SDL_ASSERTION_REPORT_DISABLED
|
||||
static SDL_assert_data assertion_list_terminator = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
static SDL_assert_data *triggered_assertions = &assertion_list_terminator;
|
||||
#endif
|
||||
|
||||
static SDL_mutex *assertion_mutex = NULL;
|
||||
static SDL_AssertionHandler assertion_handler = SDL_PromptAssertion;
|
||||
static void *assertion_userdata = NULL;
|
||||
|
||||
#ifdef __GNUC__
|
||||
static void
|
||||
@ -198,27 +202,30 @@ SDL_PromptAssertion_windows(const SDL_assert_data *data)
|
||||
|
||||
static void SDL_AddAssertionToReport(SDL_assert_data *data)
|
||||
{
|
||||
#if !SDL_ASSERTION_REPORT_DISABLED
|
||||
/* (data) is always a static struct defined with the assert macros, so
|
||||
we don't have to worry about copying or allocating them. */
|
||||
if (data->next == NULL) { /* not yet added? */
|
||||
data->next = triggered_assertions;
|
||||
triggered_assertions = data;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void SDL_GenerateAssertionReport(void)
|
||||
{
|
||||
#if !SDL_ASSERTION_REPORT_DISABLED
|
||||
if (triggered_assertions != &assertion_list_terminator)
|
||||
{
|
||||
SDL_assert_data *item = triggered_assertions;
|
||||
const SDL_assert_data *item;
|
||||
|
||||
/* only do this if the app hasn't assigned an assertion handler. */
|
||||
if (assertion_handler != SDL_PromptAssertion)
|
||||
return;
|
||||
|
||||
item = SDL_GetAssertionReport();
|
||||
if (item->condition)
|
||||
{
|
||||
debug_print("\n\nSDL assertion report.\n");
|
||||
debug_print("All SDL assertions between last init/quit:\n\n");
|
||||
|
||||
while (item != &assertion_list_terminator) {
|
||||
while (item->condition) {
|
||||
debug_print(
|
||||
"'%s'\n"
|
||||
" * %s (%s:%d)\n"
|
||||
@ -232,9 +239,8 @@ static void SDL_GenerateAssertionReport(void)
|
||||
}
|
||||
debug_print("\n");
|
||||
|
||||
triggered_assertions = &assertion_list_terminator;
|
||||
SDL_ResetAssertionReport();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SDL_ExitProcess(int exitcode)
|
||||
@ -253,12 +259,15 @@ static void SDL_AbortAssertion(void)
|
||||
}
|
||||
|
||||
|
||||
static SDL_assert_state SDL_PromptAssertion(const SDL_assert_data *data)
|
||||
static SDL_assert_state
|
||||
SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
|
||||
{
|
||||
const char *envr;
|
||||
SDL_assert_state state = SDL_ASSERTION_ABORT;
|
||||
SDL_WindowID window;
|
||||
|
||||
(void) userdata; /* unused in default handler. */
|
||||
|
||||
debug_print("\n\n"
|
||||
"Assertion failure at %s (%s:%d), triggered %u time%s:\n"
|
||||
" '%s'\n"
|
||||
@ -291,6 +300,7 @@ static SDL_assert_state SDL_PromptAssertion(const SDL_assert_data *data)
|
||||
if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
|
||||
SDL_MinimizeWindow(window);
|
||||
} else {
|
||||
/* !!! FIXME: ungrab the input if we're not fullscreen? */
|
||||
/* No need to mess with the window */
|
||||
window = 0;
|
||||
}
|
||||
@ -344,8 +354,6 @@ static SDL_assert_state SDL_PromptAssertion(const SDL_assert_data *data)
|
||||
}
|
||||
|
||||
|
||||
static SDL_mutex *assertion_mutex = NULL;
|
||||
|
||||
SDL_assert_state
|
||||
SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file,
|
||||
int line)
|
||||
@ -391,7 +399,7 @@ SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file,
|
||||
}
|
||||
|
||||
if (!data->always_ignore) {
|
||||
state = SDL_PromptAssertion(data);
|
||||
state = assertion_handler(data, assertion_userdata);
|
||||
}
|
||||
|
||||
switch (state)
|
||||
@ -417,8 +425,6 @@ SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file,
|
||||
return state;
|
||||
}
|
||||
|
||||
#endif /* SDL_ASSERT_LEVEL > 0 */
|
||||
|
||||
|
||||
int SDL_AssertionsInit(void)
|
||||
{
|
||||
@ -428,13 +434,41 @@ int SDL_AssertionsInit(void)
|
||||
|
||||
void SDL_AssertionsQuit(void)
|
||||
{
|
||||
#if (SDL_ASSERT_LEVEL > 0)
|
||||
SDL_GenerateAssertionReport();
|
||||
if (assertion_mutex != NULL) {
|
||||
SDL_DestroyMutex(assertion_mutex);
|
||||
assertion_mutex = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDL_SetAssertionHandler(SDL_AssertionHandler handler, void *userdata)
|
||||
{
|
||||
if (handler != NULL) {
|
||||
assertion_handler = handler;
|
||||
assertion_userdata = userdata;
|
||||
} else {
|
||||
assertion_handler = SDL_PromptAssertion;
|
||||
assertion_userdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const SDL_assert_data *SDL_GetAssertionReport(void)
|
||||
{
|
||||
return triggered_assertions;
|
||||
}
|
||||
|
||||
void SDL_ResetAssertionReport(void)
|
||||
{
|
||||
SDL_assert_data *item = triggered_assertions;
|
||||
SDL_assert_data *next = NULL;
|
||||
for (item = triggered_assertions; item->condition; item = next) {
|
||||
next = (SDL_assert_data *) item->next;
|
||||
item->always_ignore = SDL_FALSE;
|
||||
item->trigger_count = 0;
|
||||
item->next = NULL;
|
||||
}
|
||||
|
||||
triggered_assertions = &assertion_list_terminator;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
Loading…
x
Reference in New Issue
Block a user