diff options
author | Tristan Riehs <tristan.riehs@bordeaux-inp.fr> | 2024-06-22 16:19:05 +0900 |
---|---|---|
committer | Tristan Riehs <tristan.riehs@bordeaux-inp.fr> | 2024-06-22 16:19:05 +0900 |
commit | 7119092665e1b771b04b305813be81e9892dfc1b (patch) | |
tree | 3856526163d627c16e83d86873337aea03199b16 /src | |
parent | 14e0d1887808a3d8233dd14877bce7da2fe8ca12 (diff) |
Improve disp API and implement dynamic reload
Diffstat (limited to 'src')
-rw-r--r-- | src/disp.c | 77 | ||||
-rw-r--r-- | src/disp.h | 20 |
2 files changed, 75 insertions, 22 deletions
@@ -25,10 +25,6 @@ #include "disp.h" -/* Reserved return values for the read_input function. */ -#define DISP_ERR INT_MAX -#define DISP_RELOAD (INT_MAX - 1) - #define dlsym_and_check(dest, name) \ dest->name = dlsym(dest->dl_handle, #name); \ if ((!dest->name) || (dest->name == dest->dl_handle)) { \ @@ -36,42 +32,85 @@ fprintf(stderr, "calculer: %s\n", msg); \ dlclose(dest->dl_handle); \ free(dest); \ - return NULL; \ + return -1; \ } -struct disp * -get_disp(char *disp_name) +static int +load_symbols(struct disp *disp) { -#ifndef NDEBUG - /* displays are shared libraries */ - char so_path[64] = {0}; - strcpy(so_path, "./src/.libs/"); - strcat(so_path, disp_name); - strcat(so_path, ".so.0.0.0"); - void *handle = dlopen(so_path, RTLD_LAZY); + void *handle = dlopen(disp->so_path, RTLD_LAZY); if (!handle) { - char *msg = dlerror(); - fprintf(stderr, "calculer: %s\n", msg); + fprintf(stderr, "calculer: %s\n", dlerror()); exit(1); } - printf("INFO: successfully loaded symbols from \"%s\"\n", so_path); +#ifndef NDEBUG + printf("INFO: successfully loaded symbols from \"%s\"\n", disp->so_path); +#endif - struct disp *disp = malloc(sizeof(*disp)); disp->dl_handle = handle; dlsym_and_check(disp, init); dlsym_and_check(disp, display_calc); dlsym_and_check(disp, read_input); dlsym_and_check(disp, display_res); dlsym_and_check(disp, destroy); +#ifndef NDEBUG dlsym_and_check(disp, pre_reload); dlsym_and_check(disp, post_reload); +#endif + return 0; +} - return disp; +struct disp * +get_disp(char *disp_name) +{ +#ifndef NDEBUG + /* displays are shared libraries */ + char so_path[64] = {0}; + strcpy(so_path, "./src/.libs/"); + strcat(so_path, disp_name); + strcat(so_path, ".so.0.0.0"); + struct disp *disp = malloc(sizeof(*disp)); + disp->so_path = strdup(so_path); + + return load_symbols(disp) == 0 ? disp : NULL; #else # error "not available yet" #endif return NULL; } + +void +destroy_disp(struct disp *disp) +{ + disp->destroy(); + dlclose(disp->dl_handle); + free(disp->so_path); + free(disp); +} + +#ifndef NDEBUG +void +disp_reload(struct disp *disp) +{ + int status; + printf("INFO: saving state\n"); + void *state = disp->pre_reload(); + printf("INFO: closing shared library\n"); + dlclose(disp->dl_handle); + printf("INFO: reloading symbols\n"); + status = load_symbols(disp); + + if (status == -1) + { + printf("calculer: %s\n", dlerror()); + exit(1); + } + + printf("INFO: loading state\n"); + disp->post_reload(state); + printf("INFO: reloading done\n"); +} +#endif @@ -18,11 +18,19 @@ #define DISP_H #include <stdbool.h> +#include <limits.h> /* Available display types. */ #define DISP_CLI "cli" #define DISP_RAY "ray" +/* Reserved return values for the read_input function. */ +#ifndef NDEBUG +# define DISP_RELOAD INT_MAX +#endif +#define DISP_QUIT (INT_MAX - 1) +#define DISP_ERR (INT_MAX - 2) + struct disp { void *dl_handle; void (*init)(void); @@ -30,13 +38,19 @@ struct disp { int (*read_input)(void); void (*display_res)(bool, int); void (*destroy)(void); +#ifndef NDEBUG + char *so_path; void *(*pre_reload)(void); void (*post_reload)(void *); +#endif }; /* Get a display handler for the given display type. */ -struct disp *get_disp(char *disp_name); +struct disp *get_disp(char *); +void destroy_disp(struct disp *); -void destroy_disp(void); +#ifndef NDEBUG +void disp_reload(struct disp *); +#endif /* NDEBUG */ -#endif +#endif /* DISP_H */ |