1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      List of functions to call at program cleanup.
12  *
13  *      By Shawn Hargreaves.
14  *
15  *      See LICENSE.txt for copyright information.
16  */
17 
18 
19 #include "allegro5/allegro.h"
20 #include "allegro5/internal/aintern_exitfunc.h"
21 
22 
23 /* dynamic registration system for cleanup code */
24 struct al_exit_func {
25    void (*funcptr)(void);
26    const char *desc;
27    struct al_exit_func *next;
28 };
29 
30 static struct al_exit_func *exit_func_list = NULL;
31 
32 
33 
34 /* _al_add_exit_func:
35  *  Adds a function to the list that need to be called on Allegro shutdown.
36  *  `desc' should point to a statically allocated string to help with
37  *  debugging.
38  */
_al_add_exit_func(void (* func)(void),const char * desc)39 void _al_add_exit_func(void (*func)(void), const char *desc)
40 {
41    struct al_exit_func *n;
42 
43    for (n = exit_func_list; n; n = n->next)
44       if (n->funcptr == func)
45          return;
46 
47    n = al_malloc(sizeof(struct al_exit_func));
48    if (!n)
49       return;
50 
51    n->next = exit_func_list;
52    n->funcptr = func;
53    n->desc = desc;
54    exit_func_list = n;
55 }
56 
57 
58 
59 /* _al_remove_exit_func:
60  *  Removes a function from the list that need to be called on Allegro
61  *  shutdown.
62  */
_al_remove_exit_func(void (* func)(void))63 void _al_remove_exit_func(void (*func)(void))
64 {
65    struct al_exit_func *iter = exit_func_list, *prev = NULL;
66 
67    while (iter) {
68       if (iter->funcptr == func) {
69          if (prev)
70             prev->next = iter->next;
71          else
72             exit_func_list = iter->next;
73          al_free(iter);
74          return;
75       }
76       prev = iter;
77       iter = iter->next;
78    }
79 }
80 
81 
82 
83 /* _al_run_exit_funcs:
84  *  Run all the functions registered with _al_add_exit_func, in reverse order of
85  *  registration.
86  */
_al_run_exit_funcs(void)87 void _al_run_exit_funcs(void)
88 {
89    while (exit_func_list) {
90       void (*func)(void) = exit_func_list->funcptr;
91       _al_remove_exit_func(func);
92       (*func)();
93    }
94 }
95 
96 
97 /* vim: set sts=3 sw=3 et: */
98