Slightly better handling of plugin reloading.

This commit is contained in:
Fyren 2016-06-02 00:03:52 +00:00
parent b9f7f20046
commit 4e654704dc
2 changed files with 53 additions and 20 deletions

View File

@ -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,14 +2019,23 @@ 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
{
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))
{
return false;
}
if (!(newpl=LoadPlugin(filename, true, ptype, NULL, 0, &wasloaded)))
if (pl->State() == PluginState::WaitingToUnload)
{
pl->SetWaitingToUnload(true);
ScheduleTaskForNextFrame([this, id, filename, ptype, print]() -> void {
ReloadPluginImpl(id, filename.chars(), ptype, print);
});
}
return false;
}
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)
{
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<CPlugin *>(newpl));
PluginIter iter(m_plugins);
@ -2073,8 +2106,6 @@ bool CPluginManager::ReloadPlugin(CPlugin *pl)
// Empty loop.
}
m_plugins.insertBefore(iter, static_cast<CPlugin *>(newpl));
return true;
}
void CPluginManager::RefreshAll()

View File

@ -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: