<<
path:
root/public/gist.git/html/jai/hot_reload/src/host.jai
blob: 809a675e1318f1ac88f2f72cb60f7725a5aaa3b8
[raw]
[clear marker]
5editor_main: Editor_Main;
13WATCH_FILE :: "main.jai";
15FILE_WATCHER_LOG :: false;
17MAX_RETRY_DEFAULT :: 20;
18DELAY_MS_DEFAULT :s32: 500;
19DELAY_MS_MAX :s32: 8000;
21BLOCK_TILL_EVENT :: -1;
22MAX_WAIT_SECONDS :: 20_000.0;
25Editor_Main :: #type (ctx: *#Context);
29 log("Hello from Host");
30 log("FP: %", FP_EDITOR_SO);
31 log("DEF: %", *context);
33 log("Temporary_Storage uses % bytes.", context.temporary_storage.total_bytes_occupied);
34 log("-------------------------------");
36 if !file_watcher_init(WATCH_DIR) return;
39 max_retry := MAX_RETRY_DEFAULT;
40 delay_ms := DELAY_MS_DEFAULT;
43 wait_seconds: float64;
52 reset_temporary_storage();
55 event_fds := poll(poll_fds.data, xx poll_fds.count, BLOCK_TILL_EVENT);
58 action := poll_error(event_fds);
60 if #complete action == {
62 case .RETRY; if exp_backoff() then continue; else return;
63 case .SIGNAL; continue;
67 fms := wait_seconds * 1000.0;
68 fms = clamp(fms, 0.0, MAX_WAIT_SECONDS);
70 assert(fms < MAX_WAIT_SECONDS, "Unexpected high timeout");
71 if fms == MAX_WAIT_SECONDS {
72 log("process_changes() returned a high timeout!", flags=.WARNING);
75 ms := cast(s32, round(xx fms));
76 sleep_milliseconds(ms);
79 _, needs_wait=, wait_seconds= := process_changes(*watcher);
82 do_hot_reload = false;
88 while !thread_is_done(thread) {}
93 CMD :: string.[ "jai", "build.jai", "-", "silent", "hotreload", "rebuild" ];
94 if run_command(..CMD, print_captured_output=true).exit_code != 0 {
102 lib = dlopen(FP_EDITOR_SO, RTLD_NOW);
103 editor_main = cast(Editor_Main)dlsym(lib, "hotreload_main");
104 editor_main(*context);
105 log("Temporary_Storage uses % bytes.", context.temporary_storage.total_bytes_occupied);
108file_watcher_init :: (dir: string) -> ok: bool = false {
109 if !file_exists(FP_EDITOR_SO) return;
113 file_change_callback,
114 events_to_watch = .ALL_EVENTS,
115 verbose=FILE_WATCHER_LOG)
117 log_error("Could not initialize watcher");
121 if !add_directories(*watcher, dir) {
122 log_error("Could not watch directory %", FP_EDITOR_SO);
126 poll_fds[0].fd = watcher.inotify_instance;
127 poll_fds[0].events = POLLIN;
129 log("INotify armed");
133file_change_callback :: (watcher: *File_Watcher(void), change: *File_Change, _: *void) {
134 if !ends_with(change.full_path, WATCH_FILE) return;
135 do_hot_reload = true;
138exp_backoff :: () -> should_continue: bool #expand {
140 log_error("POLL: Cannot recover!");
143 log("POLL: Retry attempt left: % with % ms delay",
150 sleep_milliseconds(`delay_ms);
152 `delay_ms = min(`delay_ms, DELAY_MS_MAX);
157poll_error :: (rc: s32) -> enum { EXIT; RETRY; SIGNAL; } {
159 /** The allocation of internal data structures failed but a subsequent request may succeed. */
161 log("POLL: Internal allocation failed.", flags=.WARNING);
164 /** A signal was caught during poll(). */
168 /** The nfds argument is greater than {OPEN_MAX}, or one of the fd members refers to a
169 STREAM or multiplexer that is linked (directly or indirectly) downstream from
173 log_error("POLL: More FDs then supported. Or something else.");
176 log_error("Unknown poll() error. Maybe your ABI version is more recent. My bad.");
185#import "File_Watcher";
186#import "File_Utilities";