]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Rework dynamic_reference management, introduce dynamic_reference_nocheck
authorattilamolnar <attilamolnar@hush.com>
Thu, 4 Apr 2013 20:09:21 +0000 (22:09 +0200)
committerattilamolnar <attilamolnar@hush.com>
Mon, 8 Apr 2013 21:13:24 +0000 (23:13 +0200)
New dynamic references are now resolved at construction and all of them are re-resolved when a relevant service is added or removed; resolution is no longer done in operator->

dynamic_reference_nocheck is a variant of dynamic_reference that does not check for value being null in operator-> / operator*
dynamic_reference still throws an exception when used in this case

Both kinds of dynamic references support .check(): an exception is thrown if this is called when value is null

include/modules.h
src/inspircd.cpp
src/modules.cpp

index e09245de90ebbc29a269888ee769582a6af1c476..ac90d60e7241649f1f2bb0b3b86805f84cdf4b48 100644 (file)
@@ -286,32 +286,61 @@ class CoreExport dynamic_reference_base : public interfacebase
 {
  private:
        std::string name;
+       void resolve();
  protected:
        DataProvider* value;
  public:
        ModuleRef creator;
        dynamic_reference_base(Module* Creator, const std::string& Name);
        ~dynamic_reference_base();
-       inline void ClearCache() { value = NULL; }
        inline const std::string& GetProvider() { return name; }
        void SetProvider(const std::string& newname);
-       void lookup();
-       operator bool();
+       void check();
+       operator bool() { return (value != NULL); }
        static void reset_all();
 };
 
+inline void dynamic_reference_base::check()
+{
+       if (!value)
+               throw ModuleException("Dynamic reference to '" + name + "' failed to resolve");
+}
+
 template<typename T>
 class dynamic_reference : public dynamic_reference_base
 {
  public:
        dynamic_reference(Module* Creator, const std::string& Name)
                : dynamic_reference_base(Creator, Name) {}
+
        inline T* operator->()
        {
-               if (!value)
-                       lookup();
+               check();
                return static_cast<T*>(value);
        }
+
+       T* operator*()
+       {
+               return operator->();
+       }
+};
+
+template<typename T>
+class dynamic_reference_nocheck : public dynamic_reference_base
+{
+ public:
+       dynamic_reference_nocheck(Module* Creator, const std::string& Name)
+               : dynamic_reference_base(Creator, Name) {}
+
+       T* operator->()
+       {
+               return static_cast<T*>(value);
+       }
+
+       T* operator*()
+       {
+               return operator->();
+       }
 };
 
 /** Priority types which can be used by Module::Prioritize()
index cccf3fe893ecd1a5204a0db42e9787c454c68c69..b3c4ca27dce0e9e1160791153542b69592dfb52a 100644 (file)
@@ -347,6 +347,7 @@ InspIRCd::InspIRCd(int argc, char** argv) :
        this->SNO = new SnomaskManager;
        this->BanCache = new BanCacheManager;
        this->Modules = new ModuleManager();
+       dynamic_reference_base::reset_all();
        this->stats = new serverstats();
        this->Timers = new TimerManager;
        this->Parser = new CommandParser;
index 56f50eb2907f903b2855c82908cfb305f0d7e496..b09639b2eaabd7ddd3e38b6d76066502bf61ac0b 100644 (file)
 #endif
 
 static std::vector<dynamic_reference_base*>* dynrefs = NULL;
+static bool dynref_init_complete = false;
 
 void dynamic_reference_base::reset_all()
 {
+       dynref_init_complete = true;
        if (!dynrefs)
                return;
        for(unsigned int i = 0; i < dynrefs->size(); i++)
-               (*dynrefs)[i]->ClearCache();
+               (*dynrefs)[i]->resolve();
 }
 
 // Version is a simple class for holding a modules version number
@@ -449,6 +451,7 @@ void ModuleManager::AddService(ServiceProvider& item)
                                DataProviders.insert(std::make_pair(item.name.substr(0, slash), &item));
                                DataProviders.insert(std::make_pair(item.name.substr(slash + 1), &item));
                        }
+                       dynamic_reference_base::reset_all();
                        return;
                }
                default:
@@ -505,6 +508,8 @@ dynamic_reference_base::dynamic_reference_base(Module* Creator, const std::strin
        if (!dynrefs)
                dynrefs = new std::vector<dynamic_reference_base*>;
        dynrefs->push_back(this);
+       if (dynref_init_complete)
+               resolve();
 }
 
 dynamic_reference_base::~dynamic_reference_base()
@@ -530,24 +535,16 @@ dynamic_reference_base::~dynamic_reference_base()
 void dynamic_reference_base::SetProvider(const std::string& newname)
 {
        name = newname;
-       ClearCache();
-}
-
-void dynamic_reference_base::lookup()
-{
-       if (!*this)
-               throw ModuleException("Dynamic reference to '" + name + "' failed to resolve");
+       resolve();
 }
 
-dynamic_reference_base::operator bool()
+void dynamic_reference_base::resolve()
 {
-       if (!value)
-       {
-               std::multimap<std::string, ServiceProvider*>::iterator i = ServerInstance->Modules->DataProviders.find(name);
-               if (i != ServerInstance->Modules->DataProviders.end())
-                       value = static_cast<DataProvider*>(i->second);
-       }
-       return (value != NULL);
+       std::multimap<std::string, ServiceProvider*>::iterator i = ServerInstance->Modules->DataProviders.find(name);
+       if (i != ServerInstance->Modules->DataProviders.end())
+               value = static_cast<DataProvider*>(i->second);
+       else
+               value = NULL;
 }
 
 void InspIRCd::SendMode(const std::vector<std::string>& parameters, User *user)