Fix re-entrancy issues in CPluginManager by using ReentrantList.

This commit is contained in:
David Anderson 2015-09-19 19:00:58 -07:00
parent 709149fbed
commit ab1b915a3c
3 changed files with 98 additions and 178 deletions

View File

@ -727,10 +727,12 @@ void CPlugin::BindFakeNativesTo(CPlugin *other)
* PLUGIN ITERATOR * * PLUGIN ITERATOR *
*******************/ *******************/
CPluginManager::CPluginIterator::CPluginIterator(List<CPlugin *> *_mylist) CPluginManager::CPluginIterator::CPluginIterator(ReentrantList<CPlugin *>& in)
{ {
mylist = _mylist; for (PluginIter iter(in); !iter.done(); iter.next())
Reset(); mylist.append(*iter);
current = mylist.begin();
g_PluginSys.AddPluginsListener(this);
} }
IPlugin *CPluginManager::CPluginIterator::GetPlugin() IPlugin *CPluginManager::CPluginIterator::GetPlugin()
@ -740,7 +742,7 @@ IPlugin *CPluginManager::CPluginIterator::GetPlugin()
bool CPluginManager::CPluginIterator::MorePlugins() bool CPluginManager::CPluginIterator::MorePlugins()
{ {
return (current != mylist->end()); return (current != mylist.end());
} }
void CPluginManager::CPluginIterator::NextPlugin() void CPluginManager::CPluginIterator::NextPlugin()
@ -750,16 +752,20 @@ void CPluginManager::CPluginIterator::NextPlugin()
void CPluginManager::CPluginIterator::Release() void CPluginManager::CPluginIterator::Release()
{ {
g_PluginSys.ReleaseIterator(this); delete this;
} }
CPluginManager::CPluginIterator::~CPluginIterator() CPluginManager::CPluginIterator::~CPluginIterator()
{ {
g_PluginSys.RemovePluginsListener(this);
} }
void CPluginManager::CPluginIterator::Reset() void CPluginManager::CPluginIterator::OnPluginDestroyed(IPlugin *plugin)
{ {
current = mylist->begin(); if (*current == plugin)
current = mylist.erase(current);
else
mylist.remove(static_cast<CPlugin *>(plugin));
} }
/****************** /******************
@ -783,8 +789,7 @@ void CPluginManager::Shutdown()
{ {
List<CPlugin *>::iterator iter; List<CPlugin *>::iterator iter;
while ((iter = m_plugins.begin()) != m_plugins.end()) for (PluginIter iter(m_plugins); !iter.done(); iter.next()) {
{
UnloadPlugin(*iter); UnloadPlugin(*iter);
} }
} }
@ -968,31 +973,20 @@ void CPluginManager::LoadAutoPlugin(const char *plugin)
void CPluginManager::AddPlugin(CPlugin *pPlugin) void CPluginManager::AddPlugin(CPlugin *pPlugin)
{ {
List<IPluginsListener *>::iterator iter; for (ListenerIter iter(m_listeners); !iter.done(); iter.next())
IPluginsListener *pListener; (*iter)->OnPluginCreated(pPlugin);
for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++) m_plugins.append(pPlugin);
{
pListener = (*iter);
pListener->OnPluginCreated(pPlugin);
}
m_plugins.push_back(pPlugin);
m_LoadLookup.insert(pPlugin->GetFilename(), pPlugin); m_LoadLookup.insert(pPlugin->GetFilename(), pPlugin);
} }
void CPluginManager::LoadAll_SecondPass() void CPluginManager::LoadAll_SecondPass()
{ {
List<CPlugin *>::iterator iter; for (PluginIter iter(m_plugins); !iter.done(); iter.next()) {
CPlugin *pPlugin; CPlugin *pPlugin = (*iter);
char error[256];
for (iter=m_plugins.begin(); iter!=m_plugins.end(); iter++)
{
pPlugin = (*iter);
if (pPlugin->GetStatus() == Plugin_Loaded) if (pPlugin->GetStatus() == Plugin_Loaded)
{ {
error[0] = '\0'; char error[256] = {0};
if (!RunSecondPass(pPlugin, error, sizeof(error))) if (!RunSecondPass(pPlugin, error, sizeof(error)))
{ {
g_Logger.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error); g_Logger.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error);
@ -1048,7 +1042,7 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size
pPlugin->AddRequiredLib(name); pPlugin->AddRequiredLib(name);
CPlugin *found; CPlugin *found;
for (auto iter=m_plugins.begin(); iter!=m_plugins.end(); iter++) { for (PluginIter iter(m_plugins); !iter.done(); iter.next()) {
CPlugin *pl = (*iter); CPlugin *pl = (*iter);
if (pl->HasLibrary(name)) { if (pl->HasLibrary(name)) {
found = pl; found = pl;
@ -1262,13 +1256,8 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng
} }
/* Finish by telling all listeners */ /* Finish by telling all listeners */
List<IPluginsListener *>::iterator iter; for (ListenerIter iter(m_listeners); !iter.done(); iter.next())
IPluginsListener *pListener; (*iter)->OnPluginLoaded(pPlugin);
for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++)
{
pListener = (*iter);
pListener->OnPluginLoaded(pPlugin);
}
/* Tell this plugin to finish initializing itself */ /* Tell this plugin to finish initializing itself */
pPlugin->Call_OnPluginStart(); pPlugin->Call_OnPluginStart();
@ -1276,12 +1265,8 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng
/* Now, if we have fake natives, go through all plugins that might need rebinding */ /* Now, if we have fake natives, go through all plugins that might need rebinding */
if (pPlugin->GetStatus() <= Plugin_Paused && pPlugin->HasFakeNatives()) if (pPlugin->GetStatus() <= Plugin_Paused && pPlugin->HasFakeNatives())
{ {
List<CPlugin *>::iterator pl_iter; for (PluginIter iter(m_plugins); !iter.done(); iter.next()) {
for (pl_iter = m_plugins.begin(); CPlugin *pOther = (*iter);
pl_iter != m_plugins.end();
pl_iter++)
{
CPlugin *pOther = (*pl_iter);
if ((pOther->GetStatus() == Plugin_Error if ((pOther->GetStatus() == Plugin_Error
&& (pOther->HasMissingFakeNatives() || pOther->HasMissingLibrary())) && (pOther->HasMissingFakeNatives() || pOther->HasMissingLibrary()))
|| pOther->HasMissingFakeNatives()) || pOther->HasMissingFakeNatives())
@ -1307,9 +1292,8 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng
pPlugin->GetPhrases()->AddPhraseFile("core.phrases"); pPlugin->GetPhrases()->AddPhraseFile("core.phrases");
/* Go through all other already loaded plugins and tell this plugin, that their libraries are loaded */ /* Go through all other already loaded plugins and tell this plugin, that their libraries are loaded */
for (List<CPlugin *>::iterator pl_iter = m_plugins.begin(); pl_iter != m_plugins.end(); pl_iter++) for (PluginIter iter(m_plugins); !iter.done(); iter.next()) {
{ CPlugin *pl = (*iter);
CPlugin *pl = (*pl_iter);
/* Don't call our own libraries again and only care for already loaded plugins */ /* Don't call our own libraries again and only care for already loaded plugins */
if (pl == pPlugin || pl->GetStatus() != Plugin_Running) if (pl == pPlugin || pl->GetStatus() != Plugin_Running)
continue; continue;
@ -1330,8 +1314,8 @@ void CPluginManager::TryRefreshDependencies(CPlugin *pPlugin)
bool all_found = pPlugin->ForEachRequiredLib([this, pPlugin] (const char *lib) -> bool { bool all_found = pPlugin->ForEachRequiredLib([this, pPlugin] (const char *lib) -> bool {
CPlugin *found = nullptr; CPlugin *found = nullptr;
for (auto pl_iter=m_plugins.begin(); pl_iter!=m_plugins.end(); pl_iter++) { for (PluginIter iter(m_plugins); !iter.done(); iter.next()) {
CPlugin *search = (*pl_iter); CPlugin *search = (*iter);
if (search->HasLibrary(lib)) { if (search->HasLibrary(lib)) {
found = search; found = search;
break; break;
@ -1390,7 +1374,7 @@ bool CPluginManager::UnloadPlugin(IPlugin *plugin)
bool CPluginManager::ScheduleUnload(CPlugin *pPlugin) bool CPluginManager::ScheduleUnload(CPlugin *pPlugin)
{ {
// Should not be recursively removing. // Should not be recursively removing.
assert(m_plugins.find(pPlugin) != m_plugins.end()); assert(m_plugins.contains(pPlugin));
IPluginContext *pContext = pPlugin->GetBaseContext(); IPluginContext *pContext = pPlugin->GetBaseContext();
if (pContext && pContext->IsInExec()) { if (pContext && pContext->IsInExec()) {
@ -1418,30 +1402,20 @@ void CPluginManager::UnloadPluginImpl(CPlugin *pPlugin)
OnLibraryAction(lib, LibraryAction_Removed); OnLibraryAction(lib, LibraryAction_Removed);
}); });
List<IPluginsListener *>::iterator iter;
IPluginsListener *pListener;
if (pPlugin->GetStatus() <= Plugin_Error || pPlugin->GetStatus() == Plugin_Failed) if (pPlugin->GetStatus() <= Plugin_Error || pPlugin->GetStatus() == Plugin_Failed)
{ {
/* Notify plugin */ /* Notify plugin */
pPlugin->Call_OnPluginEnd(); pPlugin->Call_OnPluginEnd();
/* Notify listeners of unloading */ /* Notify listeners of unloading */
for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++) for (ListenerIter iter(m_listeners); !iter.done(); iter.next())
{ (*iter)->OnPluginUnloaded(pPlugin);
pListener = (*iter);
pListener->OnPluginUnloaded(pPlugin);
}
} }
pPlugin->DropEverything(); pPlugin->DropEverything();
for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++) for (ListenerIter iter(m_listeners); !iter.done(); iter.next())
{ (*iter)->OnPluginDestroyed(pPlugin);
/* Notify listeners of destruction */
pListener = (*iter);
pListener->OnPluginDestroyed(pPlugin);
}
/* Tell the plugin to delete itself */ /* Tell the plugin to delete itself */
delete pPlugin; delete pPlugin;
@ -1469,12 +1443,12 @@ CPlugin *CPluginManager::GetPluginByCtx(const sp_context_t *ctx)
unsigned int CPluginManager::GetPluginCount() unsigned int CPluginManager::GetPluginCount()
{ {
return m_plugins.size(); return m_plugins.length();
} }
void CPluginManager::AddPluginsListener(IPluginsListener *listener) void CPluginManager::AddPluginsListener(IPluginsListener *listener)
{ {
m_listeners.push_back(listener); m_listeners.append(listener);
} }
void CPluginManager::RemovePluginsListener(IPluginsListener *listener) void CPluginManager::RemovePluginsListener(IPluginsListener *listener)
@ -1484,12 +1458,7 @@ void CPluginManager::RemovePluginsListener(IPluginsListener *listener)
IPluginIterator *CPluginManager::GetPluginIterator() IPluginIterator *CPluginManager::GetPluginIterator()
{ {
return new CPluginIterator(&m_plugins); return new CPluginIterator(m_plugins);
}
void CPluginManager::ReleaseIterator(CPluginIterator *iter)
{
delete iter;
} }
bool CPluginManager::TestAliasMatch(const char *alias, const char *localpath) bool CPluginManager::TestAliasMatch(const char *alias, const char *localpath)
@ -1803,15 +1772,11 @@ CPlugin *CPluginManager::GetPluginByOrder(int num)
return NULL; return NULL;
} }
CPlugin *pl; PluginIter iter(m_plugins);
int id = 1; for (int id = 1; !iter.done() && id < num; iter.next(), id++) {
// Empty loop.
SourceHook::List<CPlugin *>::iterator iter; }
for (iter = m_plugins.begin(); iter != m_plugins.end() && id < num; iter++, id++) {} return *iter;
pl = *iter;
return pl;
} }
const char *CPluginManager::GetStatusText(PluginStatus st) const char *CPluginManager::GetStatusText(PluginStatus st)
@ -1863,13 +1828,10 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
rootmenu->ConsolePrint("[SM] Listing %d plugin%s:", GetPluginCount(), (plnum > 1) ? "s" : ""); rootmenu->ConsolePrint("[SM] Listing %d plugin%s:", GetPluginCount(), (plnum > 1) ? "s" : "");
} }
CPlugin *pl; ke::LinkedList<CPlugin *> fail_list;
SourceHook::List<CPlugin *>::iterator iter;
SourceHook::List<CPlugin *> m_FailList;
for (iter = m_plugins.begin(); iter != m_plugins.end(); iter++, id++) for (PluginIter iter(m_plugins); !iter.done(); iter.next(), id++) {
{ CPlugin *pl = (*iter);
pl = (*iter);
assert(pl->GetStatus() != Plugin_Created); assert(pl->GetStatus() != Plugin_Created);
int len = 0; int len = 0;
const sm_plugininfo_t *info = pl->GetPublicInfo(); const sm_plugininfo_t *info = pl->GetPublicInfo();
@ -1880,7 +1842,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
if (pl->GetStatus() <= Plugin_Error) if (pl->GetStatus() <= Plugin_Error)
{ {
/* Plugin has failed to load. */ /* Plugin has failed to load. */
m_FailList.push_back(pl); fail_list.append(pl);
} }
} }
else else
@ -1908,17 +1870,11 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
rootmenu->ConsolePrint("%s", buffer); rootmenu->ConsolePrint("%s", buffer);
} }
if (!m_FailList.empty()) if (!fail_list.empty()) {
{
rootmenu->ConsolePrint("Load Errors:"); rootmenu->ConsolePrint("Load Errors:");
SourceHook::List<CPlugin *>::iterator _iter; for (auto iter = fail_list.begin(); iter != fail_list.end(); iter++) {
CPlugin *pl = (*iter);
CPlugin *pl;
for (_iter=m_FailList.begin(); _iter!=m_FailList.end(); _iter++)
{
pl = (CPlugin *)*_iter;
rootmenu->ConsolePrint("%s: %s", (IS_STR_FILLED(pl->GetPublicInfo()->name)) ? pl->GetPublicInfo()->name : pl->GetFilename(), rootmenu->ConsolePrint("%s: %s", (IS_STR_FILLED(pl->GetPublicInfo()->name)) ? pl->GetPublicInfo()->name : pl->GetFilename(),
pl->GetErrorMsg()); pl->GetErrorMsg());
} }
@ -2235,22 +2191,18 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
bool CPluginManager::ReloadPlugin(CPlugin *pl) bool CPluginManager::ReloadPlugin(CPlugin *pl)
{ {
List<CPlugin *>::iterator iter;
char filename[PLATFORM_MAX_PATH]; char filename[PLATFORM_MAX_PATH];
bool wasloaded; bool wasloaded;
PluginType ptype; PluginType ptype;
IPlugin *newpl; IPlugin *newpl;
int id = 1;
strcpy(filename, pl->GetFilename()); strcpy(filename, pl->GetFilename());
ptype = pl->GetType(); ptype = pl->GetType();
for (iter=m_plugins.begin(); iter!=m_plugins.end(); iter++, id++) int id = 1;
{ for (PluginIter iter(m_plugins); !iter.done(); iter.next(), id++) {
if ((*iter) == pl) if ((*iter) == pl)
{
break; break;
}
} }
if (!UnloadPlugin(pl)) if (!UnloadPlugin(pl))
@ -2262,20 +2214,13 @@ bool CPluginManager::ReloadPlugin(CPlugin *pl)
return false; return false;
} }
for (iter=m_plugins.begin(); iter!=m_plugins.end(); iter++) m_plugins.remove(static_cast<CPlugin *>(newpl));
{
if ((*iter) == (CPlugin *)newpl)
{
m_plugins.erase(iter);
break;
}
}
int i; PluginIter iter(m_plugins);
for (i=1, iter=m_plugins.begin(); iter!=m_plugins.end() && i<id; iter++, i++) for (int i = 1; !iter.done() && i < id; iter.next(), i++) {
{ // Empty loop.
} }
m_plugins.insert(iter, (CPlugin *)newpl); m_plugins.insertBefore(iter, static_cast<CPlugin *>(newpl));
return true; return true;
} }
@ -2288,9 +2233,7 @@ void CPluginManager::RefreshAll()
return; return;
} }
List<CPlugin *> tmp_list = m_plugins; for (PluginIter iter(m_plugins); !iter.done(); iter.next()) {
for (auto iter = tmp_list.begin(); iter != tmp_list.end(); iter++)
{
CPlugin *pl = (*iter); CPlugin *pl = (*iter);
if (pl->HasUpdatedFile()) if (pl->HasUpdatedFile())
UnloadPlugin(pl); UnloadPlugin(pl);
@ -2309,33 +2252,18 @@ bool CPlugin::HasUpdatedFile()
void CPluginManager::_SetPauseState(CPlugin *pl, bool paused) void CPluginManager::_SetPauseState(CPlugin *pl, bool paused)
{ {
List<IPluginsListener *>::iterator iter; for (ListenerIter iter(m_listeners); !iter.done(); iter.next())
IPluginsListener *pListener; (*iter)->OnPluginPauseChange(pl, paused);
for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++)
{
pListener = (*iter);
pListener->OnPluginPauseChange(pl, paused);
}
} }
void CPluginManager::AddFunctionsToForward(const char *name, IChangeableForward *pForward) void CPluginManager::AddFunctionsToForward(const char *name, IChangeableForward *pForward)
{ {
List<CPlugin *>::iterator iter; for (PluginIter iter(m_plugins); !iter.done(); iter.next()) {
CPlugin *pPlugin; CPlugin *pPlugin = (*iter);
IPluginFunction *pFunction;
for (iter = m_plugins.begin(); iter != m_plugins.end(); iter++) if (pPlugin->GetStatus() <= Plugin_Paused) {
{ if (IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionByName(name))
pPlugin = (*iter);
if (pPlugin->GetStatus() <= Plugin_Paused)
{
pFunction = pPlugin->GetBaseContext()->GetFunctionByName(name);
if (pFunction)
{
pForward->AddFunction(pFunction); pForward->AddFunction(pFunction);
}
} }
} }
} }
@ -2367,17 +2295,10 @@ void CPluginManager::OnLibraryAction(const char *lib, LibraryAction action)
bool CPluginManager::LibraryExists(const char *lib) bool CPluginManager::LibraryExists(const char *lib)
{ {
List<CPlugin *>::iterator iter; for (PluginIter iter(m_plugins); !iter.done(); iter.next()) {
for (iter=m_plugins.begin();
iter!=m_plugins.end();
iter++)
{
CPlugin *pl = (*iter); CPlugin *pl = (*iter);
if (pl->GetStatus() != Plugin_Running) if (pl->GetStatus() != Plugin_Running)
{
continue; continue;
}
if (pl->HasLibrary(lib)) if (pl->HasLibrary(lib))
return true; return true;
} }
@ -2387,21 +2308,13 @@ bool CPluginManager::LibraryExists(const char *lib)
void CPluginManager::AllPluginsLoaded() void CPluginManager::AllPluginsLoaded()
{ {
List<CPlugin *>::iterator iter; for (PluginIter iter(m_plugins); !iter.done(); iter.next())
CPlugin *pl; (*iter)->Call_OnAllPluginsLoaded();
for (iter=m_plugins.begin(); iter!=m_plugins.end(); iter++)
{
pl = (*iter);
pl->Call_OnAllPluginsLoaded();
}
} }
void CPluginManager::UnloadAll() void CPluginManager::UnloadAll()
{ {
List<CPlugin *>::iterator iter; for (PluginIter iter(m_plugins); !iter.done(); iter.next()) {
while ( (iter = m_plugins.begin()) != m_plugins.end() )
{
UnloadPlugin((*iter)); UnloadPlugin((*iter));
} }
} }
@ -2411,12 +2324,9 @@ int CPluginManager::GetOrderOfPlugin(IPlugin *pl)
int id = 1; int id = 1;
List<CPlugin *>::iterator iter; List<CPlugin *>::iterator iter;
for (iter = m_plugins.begin(); iter != m_plugins.end(); iter++, id++) for (PluginIter iter(m_plugins); !iter.done(); iter.next()) {
{
if ((*iter) == pl) if ((*iter) == pl)
{
return id; return id;
}
} }
return -1; return -1;
@ -2458,19 +2368,15 @@ void CPluginManager::OnSourceModMaxPlayersChanged(int newvalue)
void CPluginManager::SyncMaxClients(int max_clients) void CPluginManager::SyncMaxClients(int max_clients)
{ {
List<CPlugin *>::iterator iter; for (PluginIter iter(m_plugins); !iter.done(); iter.next())
for (iter = m_plugins.begin(); iter != m_plugins.end(); iter++)
{
(*iter)->SyncMaxClients(max_clients); (*iter)->SyncMaxClients(max_clients);
}
} }
const CVector<SMPlugin *> *CPluginManager::ListPlugins() const CVector<SMPlugin *> *CPluginManager::ListPlugins()
{ {
CVector<SMPlugin *> *list = new CVector<SMPlugin *>(); CVector<SMPlugin *> *list = new CVector<SMPlugin *>();
for (List<CPlugin *>::iterator iter = m_plugins.begin(); iter != m_plugins.end(); iter++) for (PluginIter iter(m_plugins); !iter.done(); iter.next())
list->push_back((*iter)); list->push_back((*iter));
return list; return list;
@ -2483,7 +2389,7 @@ void CPluginManager::FreePluginList(const CVector<SMPlugin *> *list)
void CPluginManager::ForEachPlugin(ke::Lambda<void(CPlugin *)> callback) void CPluginManager::ForEachPlugin(ke::Lambda<void(CPlugin *)> callback)
{ {
for (auto iter = m_plugins.begin(); iter != m_plugins.end(); iter++) for (PluginIter iter(m_plugins); !iter.done(); iter.next())
callback(*iter); callback(*iter);
} }

View File

@ -54,6 +54,7 @@
#include <am-string.h> #include <am-string.h>
#include <bridge/include/IScriptManager.h> #include <bridge/include/IScriptManager.h>
#include <am-function.h> #include <am-function.h>
#include <ReentrantList.h>
class CPlayer; class CPlayer;
@ -344,20 +345,21 @@ public:
~CPluginManager(); ~CPluginManager();
public: public:
/* Implements iterator class */ /* Implements iterator class */
class CPluginIterator : public IPluginIterator class CPluginIterator
: public IPluginIterator,
public IPluginsListener
{ {
public: public:
CPluginIterator(List<CPlugin *> *mylist); CPluginIterator(ReentrantList<CPlugin *>& in);
virtual ~CPluginIterator(); virtual ~CPluginIterator();
virtual bool MorePlugins(); virtual bool MorePlugins();
virtual IPlugin *GetPlugin(); virtual IPlugin *GetPlugin();
virtual void NextPlugin(); virtual void NextPlugin();
void Release(); void Release();
public: void OnPluginDestroyed(IPlugin *plugin) override;
void Reset();
private: private:
List<CPlugin *> *mylist; ke::LinkedList<CPlugin *> mylist;
List<CPlugin *>::iterator current; ke::LinkedList<CPlugin *>::iterator current;
}; };
friend class CPluginManager::CPluginIterator; friend class CPluginManager::CPluginIterator;
public: //IScriptManager public: //IScriptManager
@ -393,6 +395,7 @@ public: //IScriptManager
} }
const CVector<SMPlugin *> *ListPlugins(); const CVector<SMPlugin *> *ListPlugins();
void FreePluginList(const CVector<SMPlugin *> *plugins); void FreePluginList(const CVector<SMPlugin *> *plugins);
public: //SMGlobalClass public: //SMGlobalClass
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
void OnSourceModShutdown(); void OnSourceModShutdown();
@ -521,11 +524,6 @@ private:
bool ScheduleUnload(CPlugin *plugin); bool ScheduleUnload(CPlugin *plugin);
void UnloadPluginImpl(CPlugin *plugin); void UnloadPluginImpl(CPlugin *plugin);
protected:
/**
* Caching internal objects
*/
void ReleaseIterator(CPluginIterator *iter);
public: public:
inline IdentityToken_t *GetIdentity() inline IdentityToken_t *GetIdentity()
{ {
@ -535,8 +533,13 @@ public:
private: private:
void TryRefreshDependencies(CPlugin *pOther); void TryRefreshDependencies(CPlugin *pOther);
private: private:
List<IPluginsListener *> m_listeners; ReentrantList<IPluginsListener *> m_listeners;
List<CPlugin *> m_plugins; ReentrantList<CPlugin *> m_plugins;
ke::LinkedList<CPluginIterator *> m_iterators;
typedef decltype(m_listeners)::iterator ListenerIter;
typedef decltype(m_plugins)::iterator PluginIter;
NameHashSet<CPlugin *> m_LoadLookup; NameHashSet<CPlugin *> m_LoadLookup;
bool m_AllPluginsLoaded; bool m_AllPluginsLoaded;
IdentityToken_t *m_MyIdent; IdentityToken_t *m_MyIdent;

View File

@ -60,6 +60,7 @@ public:
class iterator class iterator
{ {
friend class ReentrantList;
public: public:
iterator(ReentrantList& list) iterator(ReentrantList& list)
: iterator(&list) : iterator(&list)
@ -145,6 +146,16 @@ public:
} }
} }
template <typename U>
void insertBefore(iterator& where, U &&obj) {
BaseType::insertBefore(where.impl_, ke::Forward<U>(obj));
}
template <typename U>
bool contains(const U &obj) {
return BaseType::find(obj) != BaseType::end();
}
private: private:
BaseTypeIter impl_begin() { BaseTypeIter impl_begin() {
return BaseType::begin(); return BaseType::begin();