Hot reloading: Finally got it working with the stat syscall

This commit is contained in:
Joseph Ferano 2024-01-10 11:42:02 +07:00
parent 93972ba1d4
commit 4b63f91494
3 changed files with 43 additions and 86 deletions

View File

@ -5,8 +5,10 @@
#include "boids_game.h"
#include "lib.h"
#define SCREEN_WIDTH 1300
#define SCREEN_HEIGHT 1080
// #define SCREEN_WIDTH 1300
// #define SCREEN_HEIGHT 1080
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
typedef struct Boid {
Point position;
@ -25,6 +27,13 @@ typedef struct GameState {
static GameState *init() {
InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Boids");
int monitor = GetCurrentMonitor();
int monitor_width = GetMonitorWidth(monitor);
// int monitor_height = GetMonitorHeight(monitor);
int win_pos_x = monitor_width - SCREEN_WIDTH - 7;
int win_pos_y = 30;
SetWindowPosition(win_pos_x, win_pos_y);
SetTargetFPS(60);
GameState *state = malloc(sizeof(struct GameApi));
@ -99,7 +108,6 @@ static int step(GameState *state) {
boid->position = Vector2Add(boid->position, boid->velocity);
}
// Update
BeginDrawing();
{
@ -113,7 +121,7 @@ static int step(GameState *state) {
DrawCircle(boid->position.x, boid->position.y, 27, BLACK);
DrawCircle(boid->position.x, boid->position.y, 20, GREEN);
}
DrawFPS(SCREEN_WIDTH - 80, 10);
}
EndDrawing();
return return_int;

View File

@ -2,10 +2,8 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <dlfcn.h>
#include <sys/epoll.h>
#include <sys/inotify.h>
// #include "inotify-syscalls.h"
#include "include/raylib.h"
#include "include/raymath.h"
#include "boids_game.h"
@ -15,11 +13,11 @@
#define TARGET_FPS 60
const char* GAME_LIB = "./libboids.so";
char epoll_buf[1024];
char inotify_buf[1024];
struct Game
{
struct Game {
void* handle;
ino_t gamelib_id;
struct GameApi api;
struct GameState* state;
};
@ -27,92 +25,43 @@ struct Game
#define MAX_EVENTS 1
void load_game(struct Game* game) {
if (game->handle) {
game->api.unload(game->state);
dlclose(game->handle);
}
void* handle = dlopen(GAME_LIB, RTLD_NOW);
if (handle) {
game->handle = handle;
const struct GameApi* api = dlsym(game->handle, "GAME_API");
if (api != NULL) {
printf("Loaded API, calling init()\n");
game->api = *api;
if (game->state == NULL) {
game->state = game->api.init();
}
game->api.reload(game->state);
} else {
printf("Failed to load API\n");
struct stat attr;
if ((stat(GAME_LIB, &attr) == 0) && (game->gamelib_id != attr.st_ino)) {
if (game->handle) {
game->api.unload(game->state);
dlclose(game->handle);
}
} else {
fprintf(stderr, "Error loading %s\n", GAME_LIB);
fprintf(stderr, "Error was: %s\n", dlerror());
exit(1);
void* handle = dlopen(GAME_LIB, RTLD_NOW);
if (handle) {
game->handle = handle;
game->gamelib_id = attr.st_ino;
const struct GameApi* api = dlsym(game->handle, "GAME_API");
if (api != NULL) {
printf("Loaded API, calling init()\n");
game->api = *api;
if (game->state == NULL) {
game->state = game->api.init();
}
game->api.reload(game->state);
} else {
printf("Failed to load API\n");
dlclose(game->handle);
}
} else {
fprintf(stderr, "Error loading %s\n", GAME_LIB);
fprintf(stderr, "Error was: %s\n", dlerror());
exit(1);
}
}
}
int main(void) {
int fd = inotify_init();
if (fd < 0) {
fprintf(stderr, "Error initializing inotify\n");
}
int wd;
wd = inotify_add_watch(fd, GAME_LIB, IN_MODIFY);
// create epoll instance
int epollfd = epoll_create1(0);
if (epollfd == -1) {
fprintf(stderr, "Error creating epoll instance\n");
}
struct epoll_event event;
event.events = EPOLLIN;
event.data.fd = fd;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event) == -1) {
fprintf(stderr, "Error adding inotify descriptor to epoll\n");
}
struct epoll_event events[MAX_EVENTS];
struct Game game = {0};
load_game(&game);
int should_exit = 0;
while (should_exit != 1) {
int nfds = epoll_wait(epollfd, events, MAX_EVENTS, 0);
if (nfds == -1) {
fprintf(stderr, "epoll_wait failed\n");
break;
}
// printf("%d %d\n", nfds, fd);
for (int n = 0; n < nfds; ++n) {
// printf("DO I EVER GET CALLED\n", events[n].data.fd, fd);
printf("DO I EVER GET CALLED\n");
if (events[n].data.fd == fd) {
printf("SO has been updated!\n");
// This clears the inotify queue so we don't get any more events
read(fd, epoll_buf, sizeof(epoll_buf));
load_game(&game);
}
}
load_game(&game);
should_exit = game.api.step(game.state);
if (should_exit == 2) {
printf("I should exit?\n");
load_game(&game);
should_exit = 0;
usleep(1000);
}
}
game.api.finalize(game.state);
free(game.state);
inotify_rm_watch(fd, wd);
close(fd);
close(epollfd);
// CloseWindow();
}

View File

@ -22,5 +22,5 @@ CLOCK: [2024-01-09 Tue 10:45]--[2024-01-09 Tue 11:15] => 0:30
:END:
** <2024-01-10 Wed>
:LOGBOOK:
CLOCK: [2024-01-10 Wed 08:10]
CLOCK: [2024-01-10 Wed 08:10]--[2024-01-10 Wed 09:40] => 1:30
:END: