server/state: Fix module modification watching and use MultiFileWatch instead of FileWatch

This commit is contained in:
Perttu Ahola 2014-10-04 08:28:09 +03:00
parent 15e9dbcc95
commit cd5cb5acee

View File

@ -216,9 +216,14 @@ struct CState: public State, public interface::Server
// crash. // crash.
interface::Mutex m_magic_mutex; // Lock for all of Urho3D interface::Mutex m_magic_mutex; // Lock for all of Urho3D
sm_<ss_, ModuleContainer> m_modules; sm_<ss_, interface::ModuleInfo> m_module_info; // Info of every seen module
sm_<ss_, ModuleContainer> m_modules; // Currently loaded modules
set_<ss_> m_unloads_requested; set_<ss_> m_unloads_requested;
sm_<ss_, sp_<interface::FileWatch>> m_module_file_watches; sm_<ss_, sp_<interface::MultiFileWatch>> m_module_file_watches;
// Module modifications are accumulated here and core:module_modified events
// are fired every event loop based on this to lump multiple modifications
// into one (generally a modification causes many notifications)
set_<ss_> m_modified_modules; // Module names
// TODO: Handle properly in reloads (unload by popping from top, then reload // TODO: Handle properly in reloads (unload by popping from top, then reload
// everything until top) // everything until top)
sv_<ss_> m_module_load_order; sv_<ss_> m_module_load_order;
@ -356,6 +361,8 @@ struct CState: public State, public interface::Server
log_i(MODULE, "Loading module %s from %s", cs(info.name), cs(info.path)); log_i(MODULE, "Loading module %s from %s", cs(info.name), cs(info.path));
m_module_info[info.name] = info;
ss_ build_dst = g_server_config.rccpp_build_path + ss_ build_dst = g_server_config.rccpp_build_path +
"/"+info.name+"."+MODULE_EXTENSION; "/"+info.name+"."+MODULE_EXTENSION;
ss_ init_cpp_path = info.path+"/"+info.name+".cpp"; ss_ init_cpp_path = info.path+"/"+info.name+".cpp";
@ -370,16 +377,18 @@ struct CState: public State, public interface::Server
files_to_watch.insert(files_to_watch.end(), includes.begin(), includes.end()); files_to_watch.insert(files_to_watch.end(), includes.begin(), includes.end());
if(m_module_file_watches.count(info.name) == 0){ if(m_module_file_watches.count(info.name) == 0){
m_module_file_watches[info.name] = sp_<interface::FileWatch>( sp_<interface::MultiFileWatch> w(interface::createMultiFileWatch());
interface::createFileWatch(files_to_watch, for(const ss_ &watch_path : files_to_watch){
[this, info]() ss_ dir_path = interface::Filesystem::strip_file_name(watch_path);
{ w->add(dir_path, [this, info, watch_path](const ss_ &modified_path){
log_i(MODULE, "Module modified: %s: %s", if(modified_path != watch_path)
cs(info.name), cs(info.path)); return;
emit_event(Event("core:module_modified", log_i(MODULE, "Module modified: %s: %s",
new interface::ModuleModifiedEvent(info.name, info.path))); cs(info.name), cs(info.path));
handle_events(); m_modified_modules.insert(info.name);
})); });
}
m_module_file_watches[info.name] = w;
} }
// Build // Build
@ -526,14 +535,13 @@ struct CState: public State, public interface::Server
interface::ModuleInfo info; interface::ModuleInfo info;
{ {
interface::MutexScope ms(m_modules_mutex); interface::MutexScope ms(m_modules_mutex);
auto it = m_modules.find(module_name); auto it = m_module_info.find(module_name);
if(it == m_modules.end()){ if(it == m_module_info.end()){
log_w(MODULE, "reload_module: Module not found: %s", log_w(MODULE, "reload_module: Module info not found: %s",
cs(module_name)); cs(module_name));
return; return;
} }
ModuleContainer *mc = &it->second; info = it->second;
info = mc->info;
} }
reload_module(info); reload_module(info);
} }
@ -711,6 +719,21 @@ struct CState: public State, public interface::Server
void handle_events() void handle_events()
{ {
// Get modified modules and push events to queue
{
interface::MutexScope ms(m_modules_mutex);
set_<ss_> modified_modules;
modified_modules.swap(m_modified_modules);
for(const ss_ &name : modified_modules){
auto it = m_module_info.find(name);
if(it == m_module_info.end())
throw Exception("Info of modified module not available");
interface::ModuleInfo &info = it->second;
emit_event(Event("core:module_modified",
new interface::ModuleModifiedEvent(
info.name, info.path)));
}
}
// Note: Locking m_modules_mutex here is not needed because no modules // Note: Locking m_modules_mutex here is not needed because no modules
// can be deleted while this is running, because modules are deleted // can be deleted while this is running, because modules are deleted
// only by this same thread. // only by this same thread.