From 4e654704dc65984f91283562dcf7cb5faa1019b3 Mon Sep 17 00:00:00 2001 From: Fyren Date: Thu, 2 Jun 2016 00:03:52 +0000 Subject: [PATCH] Slightly better handling of plugin reloading. --- core/logic/PluginSys.cpp | 65 +++++++++++++++++++++++++++++----------- core/logic/PluginSys.h | 8 +++-- 2 files changed, 53 insertions(+), 20 deletions(-) diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index 7f49f8b7..339bac04 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -1192,10 +1192,11 @@ void CPlugin::SetRegistered() m_state = PluginState::Registered; } -void CPlugin::SetWaitingToUnload() +void CPlugin::SetWaitingToUnload(bool andReload) { - assert(m_state == PluginState::Registered); - m_state = PluginState::WaitingToUnload; + assert(m_state == PluginState::Registered || + (m_state == PluginState::WaitingToUnload && andReload)); + m_state = andReload ? PluginState::WaitingToUnloadAndReload : PluginState::WaitingToUnload; } void CPluginManager::LoadExtensions(CPlugin *pPlugin) @@ -1440,8 +1441,11 @@ bool CPluginManager::UnloadPlugin(IPlugin *plugin) assert(m_plugins.contains(pPlugin)); // If we're already in the unload queue, just wait. - if (pPlugin->State() == PluginState::WaitingToUnload) + if (pPlugin->State() == PluginState::WaitingToUnload || + pPlugin->State() == PluginState::WaitingToUnloadAndReload) + { return false; + } // It is not safe to unload any plugin while another is on the callstack. bool any_active = false; @@ -2015,13 +2019,22 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg else strcpy(name, pl->GetFilename()); - if (ReloadPlugin(pl)) + if (ReloadPlugin(pl, true)) { rootmenu->ConsolePrint("[SM] Plugin %s reloaded successfully.", name); } else { - rootmenu->ConsolePrint("[SM] Failed to reload plugin %s.", name); + switch (pl->State()) + { + //the unload/reload attempt next frame will print a message + case PluginState::WaitingToUnload: + case PluginState::WaitingToUnloadAndReload: + return; + + default: + rootmenu->ConsolePrint("[SM] Failed to reload plugin %s.", name); + } } return; @@ -2041,15 +2054,14 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg rootmenu->DrawGenericOption("unload_all", "Unloads all plugins"); } -bool CPluginManager::ReloadPlugin(CPlugin *pl) +bool CPluginManager::ReloadPlugin(CPlugin *pl, bool print) { - char filename[PLATFORM_MAX_PATH]; - bool wasloaded; - PluginType ptype; - IPlugin *newpl; + PluginState state = pl->State(); + if (state == PluginState::WaitingToUnloadAndReload) + return false; - strcpy(filename, pl->GetFilename()); - ptype = pl->GetType(); + ke::AString filename(pl->GetFilename()); + PluginType ptype = pl->GetType(); int id = 1; for (PluginIter iter(m_plugins); !iter.done(); iter.next(), id++) { @@ -2059,13 +2071,34 @@ bool CPluginManager::ReloadPlugin(CPlugin *pl) if (!UnloadPlugin(pl)) { + if (pl->State() == PluginState::WaitingToUnload) + { + pl->SetWaitingToUnload(true); + ScheduleTaskForNextFrame([this, id, filename, ptype, print]() -> void { + ReloadPluginImpl(id, filename.chars(), ptype, print); + }); + } return false; } - if (!(newpl=LoadPlugin(filename, true, ptype, NULL, 0, &wasloaded))) + + ReloadPluginImpl(id, filename.chars(), ptype, false); + return true; +} + +void CPluginManager::ReloadPluginImpl(int id, const char filename[], PluginType ptype, bool print) +{ + char error[128]; + bool wasloaded; + IPlugin *newpl = LoadPlugin(filename, true, ptype, error, sizeof(error), &wasloaded); + if (!newpl) { - return false; + rootmenu->ConsolePrint("[SM] Plugin %s failed to reload: %s.", filename, error); + return; } + if (print) + rootmenu->ConsolePrint("[SM] Plugin %s reloaded successfully.", filename); + m_plugins.remove(static_cast(newpl)); PluginIter iter(m_plugins); @@ -2073,8 +2106,6 @@ bool CPluginManager::ReloadPlugin(CPlugin *pl) // Empty loop. } m_plugins.insertBefore(iter, static_cast(newpl)); - - return true; } void CPluginManager::RefreshAll() diff --git a/core/logic/PluginSys.h b/core/logic/PluginSys.h index 928b39b3..43f04c7b 100644 --- a/core/logic/PluginSys.h +++ b/core/logic/PluginSys.h @@ -88,7 +88,8 @@ enum class PluginState Evicted, // The plugin is waiting to be unloaded. - WaitingToUnload + WaitingToUnload, + WaitingToUnloadAndReload, }; class CPlugin : @@ -176,7 +177,7 @@ public: return m_state; } void SetRegistered(); - void SetWaitingToUnload(); + void SetWaitingToUnload(bool andReload=false); PluginStatus GetDisplayStatus() const { return m_status; @@ -426,7 +427,7 @@ public: bool LibraryExists(const char *lib); - bool ReloadPlugin(CPlugin *pl); + bool ReloadPlugin(CPlugin *pl, bool print=false); void UnloadAll(); @@ -463,6 +464,7 @@ private: bool FindOrRequirePluginDeps(CPlugin *pPlugin); void UnloadPluginImpl(CPlugin *plugin); + void ReloadPluginImpl(int id, const char filename[], PluginType ptype, bool print); void Purge(CPlugin *plugin); public: