Mercurial > molko
changeset 182:f6497ec74b49
core: add alloc module, closes #2512
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 27 Oct 2020 16:54:18 +0100 |
parents | 867b60e6258a |
children | 604fad63bd9c |
files | examples/example-drawable.c libadventure/adventure/state/mainmenu.c libadventure/adventure/state/panic.c libadventure/adventure/state/splashscreen.c libcore/CMakeLists.txt libcore/core/alloc.c libcore/core/alloc.h libcore/core/inhibit.c libcore/core/inhibit.h libcore/core/util.c libcore/core/util.h |
diffstat | 11 files changed, 226 insertions(+), 144 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/example-drawable.c Tue Oct 27 16:18:21 2020 +0100 +++ b/examples/example-drawable.c Tue Oct 27 16:54:18 2020 +0100 @@ -18,6 +18,7 @@ #include <stdlib.h> +#include <core/alloc.h> #include <core/animation.h> #include <core/clock.h> #include <core/core.h> @@ -89,7 +90,7 @@ static void spawn(int x, int y) { - struct explosion *expl = emalloc(sizeof (struct explosion)); + struct explosion *expl = alloc(1, sizeof (struct explosion)); animation_init(&expl->anim, &explosion_sprite, 100); animation_drawable(&expl->anim, &expl->dw, x, y);
--- a/libadventure/adventure/state/mainmenu.c Tue Oct 27 16:18:21 2020 +0100 +++ b/libadventure/adventure/state/mainmenu.c Tue Oct 27 16:54:18 2020 +0100 @@ -20,6 +20,7 @@ #include <stdlib.h> #include <string.h> +#include <core/alloc.h> #include <core/event.h> #include <core/font.h> #include <core/game.h> @@ -119,7 +120,7 @@ struct font fonts[2]; /* Allocate the main menu data. */ - main = (state->data = ecalloc(1, sizeof (*main))); + main = (state->data = alloc_zero(1, sizeof (*main))); if (!font_openmem(&fonts[0], fonts_teutonic, sizeof (fonts_teutonic), 130) || !font_openmem(&fonts[1], fonts_pirata_one, sizeof (fonts_pirata_one), 30))
--- a/libadventure/adventure/state/panic.c Tue Oct 27 16:18:21 2020 +0100 +++ b/libadventure/adventure/state/panic.c Tue Oct 27 16:54:18 2020 +0100 @@ -22,6 +22,7 @@ #include <stdnoreturn.h> #include <string.h> +#include <core/alloc.h> #include <core/error.h> #include <core/event.h> #include <core/font.h> @@ -31,7 +32,6 @@ #include <core/state.h> #include <core/sys.h> #include <core/texture.h> -#include <core/util.h> #include <core/window.h> #include <ui/align.h> @@ -98,7 +98,7 @@ theme = theme_default(); font = theme->fonts[THEME_FONT_INTERFACE]; - view = ecalloc(1, sizeof (*view)); + view = alloc_zero(1, sizeof (*view)); if (!font_render(font, &view->texts[0].tex, "An unrecoverable error occured and the game cannot continue.", FOREGROUND) || !font_render(font, &view->texts[1].tex, "Please report the detailed error as provided below.", FOREGROUND) ||
--- a/libadventure/adventure/state/splashscreen.c Tue Oct 27 16:18:21 2020 +0100 +++ b/libadventure/adventure/state/splashscreen.c Tue Oct 27 16:54:18 2020 +0100 @@ -20,6 +20,7 @@ #include <stdlib.h> #include <string.h> +#include <core/alloc.h> #include <core/font.h> #include <core/game.h> #include <core/image.h> @@ -28,7 +29,6 @@ #include <core/state.h> #include <core/sys.h> #include <core/texture.h> -#include <core/util.h> #include <core/window.h> #include <ui/align.h> @@ -54,7 +54,7 @@ struct splashscreen *splash; struct font font; - splash = ecalloc(1, sizeof (*splash)); + splash = alloc_zero(1, sizeof (*splash)); splash->next = next; if (!font_openmem(&font, fonts_cubic, sizeof (fonts_cubic), 80))
--- a/libcore/CMakeLists.txt Tue Oct 27 16:18:21 2020 +0100 +++ b/libcore/CMakeLists.txt Tue Oct 27 16:54:18 2020 +0100 @@ -30,6 +30,8 @@ SOURCES ${libcore_SOURCE_DIR}/core/action.c ${libcore_SOURCE_DIR}/core/action.h + ${libcore_SOURCE_DIR}/core/alloc.c + ${libcore_SOURCE_DIR}/core/alloc.h ${libcore_SOURCE_DIR}/core/animation.c ${libcore_SOURCE_DIR}/core/animation.h ${libcore_SOURCE_DIR}/core/clock.c @@ -49,7 +51,6 @@ ${libcore_SOURCE_DIR}/core/game.h ${libcore_SOURCE_DIR}/core/image.c ${libcore_SOURCE_DIR}/core/image.h - ${libcore_SOURCE_DIR}/core/inhibit.c ${libcore_SOURCE_DIR}/core/inhibit.h ${libcore_SOURCE_DIR}/core/key.h ${libcore_SOURCE_DIR}/core/maths.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libcore/core/alloc.c Tue Oct 27 16:54:18 2020 +0100 @@ -0,0 +1,100 @@ +/* + * alloc.h -- custom allocators + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "alloc.h" +#include "error.h" +#include "panic.h" + +static void * +panic_alloc(size_t size) +{ + void *mem; + + if (!(mem = malloc(size))) + panicf("%s", strerror(errno)); + + return mem; +} + +static void * +panic_realloc(void *ptr, size_t size) +{ + void *mem; + + if (!(mem = realloc(ptr, size))) + panicf("%s", strerror(errno)); + + return mem; +} + +struct allocator allocator = { + .alloc = panic_alloc, + .realloc = panic_realloc, + .free = free +}; + +void * +alloc(size_t n, size_t size) +{ + assert(n != 0); + assert(size != 0); + + size_t total = n * size; + + if (total / n != size) + return errorf("%s", strerror(ENOMEM)), NULL; + + return allocator.alloc(total); +} + +void * +alloc_zero(size_t n, size_t size) +{ + assert(n != 0); + assert(size != 0); + + void *mem; + size_t total = n * size; + + if (total / n != size) + return errorf("%s", strerror(ENOMEM)), NULL; + + if ((mem = allocator.alloc(total))) + memset(mem, 0, total); + + return mem; +} + +void * +alloc_dup(const void *ptr, size_t size) +{ + assert(ptr); + assert(size != 0); + + void *mem; + + if ((mem = allocator.alloc(size))) + memcpy(mem, ptr, size); + + return mem; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libcore/core/alloc.h Tue Oct 27 16:54:18 2020 +0100 @@ -0,0 +1,116 @@ +/* + * alloc.h -- custom allocators + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef MOLKO_ALLOC_H +#define MOLKO_ALLOC_H + +/** + * \file alloc.h + * \brief Custom allocators. + * + * This module controls how the API should allocate memory. Although dynamic + * allocation isn't much used in the core API, it is used in few places where + * static arrays would not fit (e.g. loading maps). + * + * To change the allocator, simply modify the global allocator object. + */ + +#include <stddef.h> + +#include "util.h" + +/** + * \brief Global allocator strategy. + */ +struct allocator { + /** + * (+) Allocate some data. + * + * The default implementation uses malloc and calls \ref panic in case + * of failure. + * + * \pre size != 0 + * \param size the size to alloc + * \return A pointer to the allocated region (NULL is allowed). + */ + void *(*alloc)(size_t size); + + /** + * (+) Realloc a region. + * + * The default implementation uses malloc and calls \ref panic in case + * of failure. + * + * \pre size != 0 + * \param ptr the old region + * \param size the new size + * \return A pointer to the allocated region (NULL is allowed). + */ + void *(*realloc)(void *ptr, size_t size); + + /** + * (+) Free resources. + * + * The default implementation calls standard C free function. + * + * \param ptr the region (may be NULL) + */ + void (*free)(void *ptr); +}; + +/** + * \brief Global allocator object. + */ +extern struct allocator allocator; + +/** + * Shortcut for allocator->alloc. + * + * \pre n != 0 && size != 0 + * \param n the number of objects to allocate + * \param size the size of each object + * \return The result of allocator->alloc. + */ +void * +alloc(size_t n, size_t size) PLAT_NODISCARD; + +/** + * Shortcut for allocator->alloc and then use memset to clear memory. + * + * \pre n != 0 && size != 0 + * \param n the number of objects to allocate + * \param size the size of each object + * \return The result of allocator->alloc. + */ +void * +alloc_zero(size_t n, size_t size) PLAT_NODISCARD; + +/** + * Duplicate region pointer by ptr. + * + * This function calls \ref alloc to allocate memory. + * + * \pre ptr != NULL + * \param ptr the pointer + * \param size the size of the memory to copy + * \return The result of allocator->alloc filled with a copy of ptr. + */ +void * +alloc_dup(const void *ptr, size_t size) PLAT_NODISCARD; + +#endif /* !MOLKO_ALLOC_H */
--- a/libcore/core/inhibit.c Tue Oct 27 16:18:21 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * inhibit.c -- disable specific game behavior - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <assert.h> -#include <stdlib.h> -#include <string.h> - -#include "action.h" -#include "inhibit.h" -#include "game.h" -#include "util.h" - -static bool -update(struct action *a, unsigned int ticks) -{ - (void)ticks; - - game.inhibit = *((enum inhibit *)a->data); - - return true; -} - -static void -finish(struct action *a) -{ - free(a->data); -} - -void -inhibit_action(enum inhibit mode, struct action *a) -{ - assert(a); - - memset(a, 0, sizeof (struct action)); - a->data = ememdup(&mode, sizeof (enum inhibit)); - a->update = update; - a->finish = finish; -}
--- a/libcore/core/inhibit.h Tue Oct 27 16:18:21 2020 +0100 +++ b/libcore/core/inhibit.h Tue Oct 27 16:54:18 2020 +0100 @@ -53,16 +53,4 @@ INHIBIT_STATE_DRAW = (1 << 2) }; -/** - * Create an action to inhibit the system. - * - * The mode will replace the actual inhibit modes rather than adding new flags. - * - * \pre a != NULL - * \param mode the new mode - * \param a the action to fill - */ -void -inhibit_action(enum inhibit mode, struct action *a); - #endif /* !MOLKO_INHIBIT_H */
--- a/libcore/core/util.c Tue Oct 27 16:18:21 2020 +0100 +++ b/libcore/core/util.c Tue Oct 27 16:54:18 2020 +0100 @@ -16,49 +16,10 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <assert.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> - #include <SDL.h> -#include "panic.h" #include "util.h" -void * -emalloc(size_t size) -{ - void *mem; - - if (!(mem = malloc(size))) - panicf("%s", strerror(errno)); - - return mem; -} - -void * -ecalloc(size_t n, size_t size) -{ - void *mem; - - if (!(mem = calloc(n, size))) - panicf("%s", strerror(errno)); - - return mem; -} - -void * -ememdup(const void *ptr, size_t size) -{ - void *mem; - - if (!(mem = malloc(size))) - panicf("%s", strerror(errno)); - - return memcpy(mem, ptr, size); -} - void delay(unsigned int ms) {
--- a/libcore/core/util.h Tue Oct 27 16:18:21 2020 +0100 +++ b/libcore/core/util.h Tue Oct 27 16:54:18 2020 +0100 @@ -44,39 +44,6 @@ #define NELEM(x) sizeof ((x)) / sizeof ((x)[0]) /** - * Wrapper around malloc(3) that exits on allocation failure. - * - * \param size the size - * \return a pointer - * \post returned pointer will never be NULL - */ -void * -emalloc(size_t size) PLAT_NODISCARD; - -/** - * Wrapper around calloc(3) that exits on allocation failure. - * - * \param n the number of objects to allocate - * \param size the size per n - * \return a pointer - * \post returned pointer will never be NULL - */ -void * -ecalloc(size_t n, size_t size) PLAT_NODISCARD; - -/** - * Copy the region specified by ptr. - * - * \pre ptr != NULL - * \param ptr the pointer - * \param size the size of the memory to copy - * \return a pointer - * \post returned pointer will never be NULL - */ -void * -ememdup(const void *ptr, size_t size) PLAT_NODISCARD; - -/** * Put the thread to sleep for a given amount of milliseconds. * * \param ms the number of milliseconds to wait