summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorattilamolnar <attilamolnar@hush.com>2013-04-04 22:09:21 +0200
committerattilamolnar <attilamolnar@hush.com>2013-04-08 23:13:24 +0200
commit927937d6105d17fbcd8c85bbf185477d87264bc4 (patch)
treeef5ab7eb5c0bd6ebfce721b99e1464183a09a364
parent9fc218c005543384bcad73747a0574c8c6ab6289 (diff)
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
-rw-r--r--include/modules.h39
-rw-r--r--src/inspircd.cpp1
-rw-r--r--src/modules.cpp29
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<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()
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<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)