From 927937d6105d17fbcd8c85bbf185477d87264bc4 Mon Sep 17 00:00:00 2001 From: attilamolnar Date: Thu, 4 Apr 2013 22:09:21 +0200 Subject: Rework dynamic_reference management, introduce dynamic_reference_nocheck 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 | 39 ++++++++++++++++++++++++++++++++++----- src/inspircd.cpp | 1 + src/modules.cpp | 29 +++++++++++++---------------- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/include/modules.h b/include/modules.h index e09245de9..ac90d60e7 100644 --- a/include/modules.h +++ b/include/modules.h @@ -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 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(value); } + + T* operator*() + { + return operator->(); + } +}; + +template +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(value); + } + + T* operator*() + { + return operator->(); + } }; /** Priority types which can be used by Module::Prioritize() diff --git a/src/inspircd.cpp b/src/inspircd.cpp index cccf3fe89..b3c4ca27d 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -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; diff --git a/src/modules.cpp b/src/modules.cpp index 56f50eb29..b09639b2e 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -37,13 +37,15 @@ #endif static std::vector* 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; 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::iterator i = ServerInstance->Modules->DataProviders.find(name); - if (i != ServerInstance->Modules->DataProviders.end()) - value = static_cast(i->second); - } - return (value != NULL); + std::multimap::iterator i = ServerInstance->Modules->DataProviders.find(name); + if (i != ServerInstance->Modules->DataProviders.end()) + value = static_cast(i->second); + else + value = NULL; } void InspIRCd::SendMode(const std::vector& parameters, User *user) -- cgit v1.2.3