server/state: Automatic module reload on init.cpp modification

This commit is contained in:
Perttu Ahola 2014-09-18 16:23:07 +03:00
parent d967b13ec4
commit 2e63c4d7a6

View File

@ -84,11 +84,16 @@ struct CState: public State, public interface::Server
m_compiler->build(module_name, init_cpp_path, build_dst);
m_compiler->include_directories.pop_back();
m_module_file_watches[module_name] = sp_<interface::FileWatch>(
interface::createFileWatch({init_cpp_path}, [this, module_name]()
{
log_i(MODULE, "Module modified: %s", cs(module_name));
}));
if(m_module_file_watches.count(module_name) == 0){
m_module_file_watches[module_name] = sp_<interface::FileWatch>(
interface::createFileWatch({init_cpp_path},
[this, module_name, path]()
{
log_i(MODULE, "Module modified: %s; reloading", cs(module_name));
unload_module_u(module_name);
load_module(module_name, path);
}));
}
interface::Module *m = static_cast<interface::Module*>(
m_compiler->construct(module_name.c_str(), this));
@ -114,6 +119,7 @@ struct CState: public State, public interface::Server
handle_events();
}
// interface::Server version; doesn't directly unload
void unload_module(const ss_ &module_name)
{
interface::MutexScope ms(m_modules_mutex);
@ -123,6 +129,40 @@ struct CState: public State, public interface::Server
m_unloads_requested.insert(module_name);
}
// Direct version; internal and unsafe
void unload_module_u(const ss_ &module_name)
{
log_i(MODULE, "unload_module_u(): module_name=%s", cs(module_name));
interface::MutexScope ms(m_modules_mutex);
// Get and lock module
auto it = m_modules.find(module_name);
if(it == m_modules.end())
throw Exception(ss_()+"unload_module_u: Module not found: "+module_name);
ModuleContainer *mc = &it->second;
interface::MutexScope mc_ms(mc->mutex);
// Clear unload request
m_unloads_requested.erase(module_name);
// Delete subscriptions
{
interface::MutexScope ms(m_event_subs_mutex);
for(Event::Type type = 0; type < m_event_subs.size(); type++){
sv_<ModuleContainer*> &sublist = m_event_subs[type];
sv_<ModuleContainer*> new_sublist;
for(ModuleContainer *mc1 : sublist){
if(mc1 != mc)
new_sublist.push_back(mc1);
else
log_v(MODULE, "Removing %s subscription to event %zu",
cs(module_name), type);
}
sublist = new_sublist;
}
}
// Delete module
delete mc->module;
m_modules.erase(module_name);
}
ss_ get_modules_path()
{
return m_modules_path;
@ -161,13 +201,12 @@ struct CState: public State, public interface::Server
{
// This prevents module from being deleted while it is being called
interface::MutexScope ms(m_modules_mutex);
interface::Module *m = get_module(module_name);
auto it = m_modules.find(module_name);
if(it == m_modules.end())
return false;
ModuleContainer *mc = &it->second;
interface::MutexScope mc_ms(mc->mutex);
cb(m);
cb(mc->module);
return true;
}