mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-23 18:19:43 +01:00
85 lines
1.9 KiB
C
85 lines
1.9 KiB
C
|
#include "DeferCallbacks.h"
|
||
|
|
||
|
#include <SDL.h>
|
||
|
|
||
|
/* Callbacks to be deferred to the end of each sequence of gamestate functions
|
||
|
* in main. Useful for fixing frame-flicker glitches when doing a state
|
||
|
* transition in a function that gets executed before the render function.
|
||
|
*
|
||
|
* We store a linked list of callbacks, to allow for the possibility of having
|
||
|
* more than one callback active at a time (otherwise we could easily just
|
||
|
* have a single pointer here and the header would only be 1 line and an
|
||
|
* include guard) and to do it without having to allocate memory at runtime.
|
||
|
*/
|
||
|
|
||
|
static struct DEFER_Callback* head = NULL;
|
||
|
|
||
|
/* Add a callback. Don't call this directly; use the DEFER_CALLBACK macro. */
|
||
|
void DEFER_add_callback(struct DEFER_Callback* callback)
|
||
|
{
|
||
|
struct DEFER_Callback* node;
|
||
|
|
||
|
/* Are we adding the first node? */
|
||
|
if (head == NULL)
|
||
|
{
|
||
|
head = callback;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Time to walk the linked list */
|
||
|
node = head;
|
||
|
|
||
|
if (node == callback)
|
||
|
{
|
||
|
goto fail;
|
||
|
}
|
||
|
|
||
|
while (node->next != NULL)
|
||
|
{
|
||
|
node = node->next;
|
||
|
|
||
|
if (node == callback)
|
||
|
{
|
||
|
goto fail;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* We're at the end */
|
||
|
node->next = callback;
|
||
|
|
||
|
/* Success! */
|
||
|
return;
|
||
|
|
||
|
fail:
|
||
|
/* Having multiple instances of a callback isn't well-defined
|
||
|
* and is a bit complicated to reason about */
|
||
|
SDL_assert(0 && "Duplicate callback added!");
|
||
|
}
|
||
|
|
||
|
/* Call each callback in the list, along with deleting the entire list. */
|
||
|
void DEFER_execute_callbacks(void)
|
||
|
{
|
||
|
struct DEFER_Callback* node = head;
|
||
|
struct DEFER_Callback* next;
|
||
|
|
||
|
head = NULL;
|
||
|
|
||
|
if (node == NULL)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
next = node->next;
|
||
|
node->func();
|
||
|
node->next = NULL;
|
||
|
|
||
|
while (next != NULL)
|
||
|
{
|
||
|
node = next;
|
||
|
next = node->next;
|
||
|
|
||
|
node->func();
|
||
|
node->next = NULL;
|
||
|
}
|
||
|
}
|