]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules.cpp
2.0.5 release
[user/henk/code/inspircd.git] / src / modules.cpp
index 9e5c84bfff3d8e32412b9db1773c21bcc27ac2f3..8af5b95e33e1153d9b298ae212de4f19fc78b1d6 100644 (file)
        #include <dirent.h>
 #endif
 
+static std::vector<dynamic_reference_base*>* dynrefs = NULL;
 
-// Version is a simple class for holding a modules version number
-template<>
-VersionBase<API_VERSION>::VersionBase(const std::string &desc, int flags)
-: description(desc), Flags(flags)
+void dynamic_reference_base::reset_all()
 {
+       if (!dynrefs)
+               return;
+       for(unsigned int i = 0; i < dynrefs->size(); i++)
+               (*dynrefs)[i]->ClearCache();
 }
 
-template<>
-VersionBase<API_VERSION>::VersionBase(const std::string &desc, int flags, const std::string& linkdata)
-: description(desc), Flags(flags), link_data(linkdata)
+// Version is a simple class for holding a modules version number
+Version::Version(const std::string &desc, int flags) : description(desc), Flags(flags)
 {
 }
 
-template<>
-bool VersionBase<API_VERSION>::CanLink(const std::string& other_data)
+Version::Version(const std::string &desc, int flags, const std::string& linkdata)
+: description(desc), Flags(flags), link_data(linkdata)
 {
-       return link_data == other_data;
 }
 
 Request::Request(Module* src, Module* dst, const char* idstr)
@@ -162,7 +162,7 @@ void                Module::OnNamesListItem(User*, Membership*, std::string&, std::string&) {
 ModResult      Module::OnNumeric(User*, unsigned int, const std::string&) { return MOD_RES_PASSTHRU; }
 void           Module::OnHookIO(StreamSocket*, ListenSocket*) { }
 ModResult   Module::OnAcceptConnection(int, ListenSocket*, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) { return MOD_RES_PASSTHRU; }
-void           Module::OnSendWhoLine(User*, const std::vector<std::string>&, User*, Channel*, std::string&) { }
+void           Module::OnSendWhoLine(User*, const std::vector<std::string>&, User*, std::string&) { }
 
 ModuleManager::ModuleManager() : ModCount(0)
 {
@@ -368,8 +368,8 @@ void ModuleManager::DoSafeUnload(Module* mod)
                if (curr->second->creator == mod)
                        DataProviders.erase(curr);
        }
-       for(unsigned int i = 0; i < ServerInstance->Modules->ActiveDynrefs.size(); i++)
-               ServerInstance->Modules->ActiveDynrefs[i]->ClearCache();
+
+       dynamic_reference_base::reset_all();
 
        /* Tidy up any dangling resolvers */
        ServerInstance->Res->CleanResolvers(mod);
@@ -386,6 +386,29 @@ void ModuleManager::DoSafeUnload(Module* mod)
        ServerInstance->BuildISupport();
 }
 
+void ModuleManager::UnloadAll()
+{
+       /* We do this more than once, so that any service providers get a
+        * chance to be unhooked by the modules using them, but then get
+        * a chance to be removed themsleves.
+        *
+        * Note: this deliberately does NOT delete the DLLManager objects
+        */
+       for (int tries = 0; tries < 4; tries++)
+       {
+               std::map<std::string, Module*>::iterator i = Modules.begin();
+               while (i != Modules.end())
+               {
+                       std::map<std::string, Module*>::iterator me = i++;
+                       if (CanUnload(me->second))
+                       {
+                               DoSafeUnload(me->second);
+                       }
+               }
+               ServerInstance->GlobalCulls.Apply();
+       }
+}
+
 std::string& ModuleManager::LastError()
 {
        return LastModuleError;
@@ -454,8 +477,7 @@ void ModuleManager::DelService(ServiceProvider& item)
                                if (curr->second == &item)
                                        DataProviders.erase(curr);
                        }
-                       for(unsigned int i = 0; i < ServerInstance->Modules->ActiveDynrefs.size(); i++)
-                               ServerInstance->Modules->ActiveDynrefs[i]->ClearCache();
+                       dynamic_reference_base::reset_all();
                        return;
                }
                default:
@@ -484,19 +506,26 @@ ServiceProvider* ModuleManager::FindService(ServiceType type, const std::string&
 dynamic_reference_base::dynamic_reference_base(Module* Creator, const std::string& Name)
        : name(Name), value(NULL), creator(Creator)
 {
-       ServerInstance->Modules->ActiveDynrefs.push_back(this);
+       if (!dynrefs)
+               dynrefs = new std::vector<dynamic_reference_base*>;
+       dynrefs->push_back(this);
 }
 
 dynamic_reference_base::~dynamic_reference_base()
 {
-       for(unsigned int i = 0; i < ServerInstance->Modules->ActiveDynrefs.size(); i++)
+       for(unsigned int i = 0; i < dynrefs->size(); i++)
        {
-               if (ServerInstance->Modules->ActiveDynrefs[i] == this)
+               if (dynrefs->at(i) == this)
                {
-                       unsigned int last = ServerInstance->Modules->ActiveDynrefs.size() - 1;
+                       unsigned int last = dynrefs->size() - 1;
                        if (i != last)
-                               ServerInstance->Modules->ActiveDynrefs[i] = ServerInstance->Modules->ActiveDynrefs[last];
-                       ServerInstance->Modules->ActiveDynrefs.erase(ServerInstance->Modules->ActiveDynrefs.begin() + last);
+                               dynrefs->at(i) = dynrefs->at(last);
+                       dynrefs->erase(dynrefs->begin() + last);
+                       if (dynrefs->empty())
+                       {
+                               delete dynrefs;
+                               dynrefs = NULL;
+                       }
                        return;
                }
        }