From 19f3ddb901a7da5512a183d62849cb84013ba891 Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Sun, 5 Feb 2017 10:37:49 +0100 Subject: [PATCH] Refactored reload heuristic of modified modules Previously I used a fixed time offset when a file change was detected. Now I trigger a reload no module file size has changed over the last 5 updates. --- src/RuntimeModuleManager.cc | 35 +++++++++++++++++++++++++++++++---- src/RuntimeModuleManager.h | 2 ++ src/main.cc | 1 - 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/RuntimeModuleManager.cc b/src/RuntimeModuleManager.cc index 1d4aeaa..825c047 100644 --- a/src/RuntimeModuleManager.cc +++ b/src/RuntimeModuleManager.cc @@ -51,7 +51,8 @@ void RuntimeModuleManager::LoadModule(RuntimeModule* module) { if ( stat_result == 0 && (module->id != attr.st_ino || module->mtime != attr.st_mtime) ) { - std::cout << "Opening module " << module->name << std::endl; + std::cout << "Opening module " << module->name + << " (size = " << attr.st_size << ")" << std::endl; void *handle = dlopen(module->name.c_str(), RTLD_NOW | RTLD_GLOBAL); if (handle) { module->handle = handle; @@ -94,17 +95,43 @@ void RuntimeModuleManager::Update(float dt) { bool RuntimeModuleManager::CheckModulesChanged() { struct stat attr; + double current_time = gGetTimeSinceStart(); + mNumUpdatesSinceLastModuleChange++; + for (int i = 0; i < mModules.size(); i++) { RuntimeModule* module = mModules[i]; bool stat_result = stat(module->name.c_str(), &attr); - if ( stat_result == 0 && - (module->id != attr.st_ino || module->mtime != attr.st_mtime) + if (stat_result != 0) { + gLog ("Error: could not stat module %s", module->name.c_str()); + abort(); + } + + if ( module->id != attr.st_ino + || module->mtime != attr.st_mtime + || module->fsize != attr.st_size + || module->fsize == 0 ) { - return true; + module->id = attr.st_ino; + module->mtime = attr.st_mtime; + module->mtimensec = attr.st_mtim.tv_nsec; + module->fsize = attr.st_size; + mNumUpdatesSinceLastModuleChange = 0; + + gLog ("Detected file change of %s: new size %d", + module->name.c_str(), attr.st_size); } } + // We have to delay the actual reload trigger to make + // sure all writes to the dynamic libraries are complete. + if (mNumUpdatesSinceLastModuleChange == 5) { + gLog ("Triggering reload"); + + return true; + } + + return false; } diff --git a/src/RuntimeModuleManager.h b/src/RuntimeModuleManager.h index 13e4f2c..ce9051b 100644 --- a/src/RuntimeModuleManager.h +++ b/src/RuntimeModuleManager.h @@ -14,6 +14,7 @@ struct RuntimeModule { void *data = nullptr; int mtime = 0; int mtimensec = 0; + off_t fsize = 0; struct module_api api; struct module_state *state = nullptr; @@ -21,6 +22,7 @@ struct RuntimeModule { struct RuntimeModuleManager { std::vector mModules; + int mNumUpdatesSinceLastModuleChange = 0; void RegisterModule(const char* name); void UnregisterModules(); diff --git a/src/main.cc b/src/main.cc index 951856c..5adb71a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -135,7 +135,6 @@ int main(void) std::cout << "Detected module update. Unloading all modules." << std::endl; module_manager.UnloadModules(); // We need to sleep to make sure we load the new files - usleep(300000); module_manager.LoadModules(); // We need to update our last timestamp to ignore the delay due // to reloading of the modules.