Skip to content

Instantly share code, notes, and snippets.

@DaseinPhaos
Last active July 2, 2022 09:59
Show Gist options
  • Save DaseinPhaos/b47a600df2abb7d35ce2718e92d54a4c to your computer and use it in GitHub Desktop.
Save DaseinPhaos/b47a600df2abb7d35ce2718e92d54a4c to your computer and use it in GitHub Desktop.
demonstrates how to hot reload config files on debug builds with odin
package hot_reload
when ODIN_DEBUG==true {
import "core:path/filepath"
import "core:os"
import "core:sync"
import "core:time"
import "core:strings"
import "core:thread"
}
import "core:fmt"
import "core:sys/windows"
foreign import kernel32 "system:Kernel32.lib"
@(default_calling_convention="std")
foreign kernel32 {
FindFirstChangeNotificationW :: proc(lpPathName: windows.LPCWSTR, bWatchSubtree: windows.BOOL, dwNotifyFilter: windows.DWORD) -> windows.HANDLE ---
FindNextChangeNotification :: proc(hChangeHandle: windows.HANDLE) -> windows.BOOL ---
FindCloseChangeNotification :: proc(hChangeHandle: windows.HANDLE) -> windows.BOOL ---
}
FILE_NOTIFY_CHANGE_LAST_WRITE :: 0x00000010
main :: proc() {
cfg : string
for {
newCfg := read_config()
if newCfg != cfg {
fmt.printf("Config changed:\n\told: [%s]\n\tnew: [%s]\n", cfg, newCfg)
cfg = newCfg
}
}
}
read_config :: proc() -> string {
cfgPath :: `H:/projects/test/config`
when ODIN_DEBUG==true {
if _cfgDirHandle == nil {
// create cfg handle, spawn thread to monitor filesystem changes
cfgDir := filepath.dir(cfgPath, context.temp_allocator)
cfgDirW := windows.utf8_to_wstring(cfgDir, context.temp_allocator)
_cfgDirHandle = FindFirstChangeNotificationW(cfgDirW, false, FILE_NOTIFY_CHANGE_LAST_WRITE)
thread.run(proc() {
for {
windows.WaitForSingleObject(_cfgDirHandle, windows.INFINITE)
time.sleep(200*time.Millisecond) // wait for some time to make sure that content gets flushed
sync.atomic_store(&_cfgDirChanged, true)
FindNextChangeNotification(_cfgDirHandle)
}
})
_cfgDirChanged = true
}
if sync.atomic_exchange(&_cfgDirChanged, false) {
// change detected, reload content
newContent, newContentOk := os.read_entire_file(cfgPath, context.allocator)
if newContentOk {
if _cfgContent != {} {
delete_string(_cfgContent, context.allocator)
}
_cfgContent = strings.string_from_ptr(&newContent[0], len(newContent))
}
}
return _cfgContent
} else {
content :: string(#load(cfgPath))
return content
}
}
when ODIN_DEBUG==true {
_cfgDirHandle : windows.HANDLE
_cfgDirChanged : bool
_cfgContent : string
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment