summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-09-30 21:55:21 +0000
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-09-30 21:55:21 +0000
commit3dc81ee1331d1b37ee85be9bf0d843e3b6827a2d (patch)
tree431e66fceef85d577d360865b3b878dc9132afc2
parent7aa5e059a8f66d91bd8b69c58c657ceb70b4baff (diff)
Add explicit reference-counting base class
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11785 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--include/base.h110
-rw-r--r--include/inspsocket.h2
-rw-r--r--include/users.h15
-rw-r--r--src/base.cpp51
-rw-r--r--src/configreader.cpp39
-rw-r--r--src/cull_list.cpp4
-rw-r--r--src/inspsocket.cpp3
-rw-r--r--src/modules/m_spanningtree/main.cpp4
-rw-r--r--src/modules/m_spanningtree/main.h2
-rw-r--r--src/modules/m_spanningtree/utils.cpp7
-rw-r--r--src/modules/m_spanningtree/utils.h2
-rw-r--r--src/users.cpp35
12 files changed, 99 insertions, 175 deletions
diff --git a/include/base.h b/include/base.h
index b66051caf..f41ea07d2 100644
--- a/include/base.h
+++ b/include/base.h
@@ -28,71 +28,69 @@ class CoreExport classbase
public:
classbase();
- // Called just prior to destruction via cull list
- virtual void cull();
+ /**
+ * Called just prior to destruction via cull list.
+ *
+ * @return true to allow the delete, or false to halt the delete
+ */
+ virtual bool cull();
virtual ~classbase();
};
-/** BoolSet is a utility class designed to hold eight bools in a bitmask.
- * Use BoolSet::Set and BoolSet::Get to set and get bools in the bitmask,
- * and Unset and Invert for special operations upon them.
+/** The base class for inspircd classes that support reference counting.
+ * Any objects that do not have a well-defined lifetime should inherit from
+ * this
*/
-class CoreExport BoolSet : public classbase
+class CoreExport refcountbase : public classbase
{
- /** Actual bit values */
- char bits;
-
+ unsigned int refcount;
public:
+ refcountbase();
+ virtual bool cull();
+ virtual ~refcountbase();
+ inline unsigned int GetReferenceCount() const { return refcount; }
+ friend class reference_base;
+};
- /** The default constructor initializes the BoolSet to all values unset.
- */
- BoolSet();
-
- /** This constructor copies the default bitmask from a char
- */
- BoolSet(char bitmask);
-
- /** The Set method sets one bool in the set.
- *
- * @param number The number of the item to set. This must be between 0 and 7.
- */
- void Set(int number);
-
- /** The Get method returns the value of one bool in the set
- *
- * @param number The number of the item to retrieve. This must be between 0 and 7.
- *
- * @return True if the item is set, false if it is unset.
- */
- bool Get(int number);
-
- /** The Unset method unsets one value in the set
- *
- * @param number The number of the item to set. This must be between 0 and 7.
- */
- void Unset(int number);
-
- /** The Unset method inverts (flips) one value in the set
- *
- * @param number The number of the item to invert. This must be between 0 and 7.
- */
- void Invert(int number);
-
- /** Compare two BoolSets
- */
- bool operator==(BoolSet other);
-
- /** OR two BoolSets together
- */
- BoolSet operator|(BoolSet other);
+class CoreExport reference_base
+{
+ protected:
+ static inline unsigned int inc(refcountbase* v) { return ++(v->refcount); }
+ static inline unsigned int dec(refcountbase* v) { return --(v->refcount); }
+};
- /** AND two BoolSets together
- */
- BoolSet operator&(BoolSet other);
+template <typename T>
+class CoreExport reference : public reference_base
+{
+ T* value;
+ public:
+ reference() : value(0) { }
+ reference(T* v) : value(v) { if (value) inc(value); }
+ reference(const reference& v) : value(v.value) { if (value) inc(value); }
+ reference<T>& operator=(const reference<T>& other)
+ {
+ if (other.value)
+ inc(other.value);
+ this->reference::~reference();
+ value = other.value;
+ return *this;
+ }
- /** Assign one BoolSet to another
- */
- bool operator=(BoolSet other);
+ ~reference()
+ {
+ if (value)
+ {
+ int rc = dec(value);
+ if (rc == 0 && value->cull())
+ delete value;
+ }
+ }
+ inline const T* operator->() const { return value; }
+ inline const T& operator*() const { return *value; }
+ inline T* operator->() { return value; }
+ inline T& operator*() { return *value; }
+ operator bool() const { return value; }
+ operator T*() const { return value; }
};
/** This class can be used on its own to represent an exception, or derived to represent a module-specific exception.
diff --git a/include/inspsocket.h b/include/inspsocket.h
index 73aa748a0..84716eae6 100644
--- a/include/inspsocket.h
+++ b/include/inspsocket.h
@@ -146,7 +146,7 @@ class CoreExport StreamSocket : public EventHandler
*/
virtual void Close();
/** This ensures that close is called prior to destructor */
- virtual void cull();
+ virtual bool cull();
};
/**
* BufferedSocket is an extendable socket class which modules
diff --git a/include/users.h b/include/users.h
index 76337b2c3..31c1c641d 100644
--- a/include/users.h
+++ b/include/users.h
@@ -62,7 +62,7 @@ class UserResolver;
/** Holds information relevent to &lt;connect allow&gt; and &lt;connect deny&gt; tags in the config file.
*/
-struct CoreExport ConnectClass : public classbase
+struct CoreExport ConnectClass : public refcountbase
{
/** Type of line, either CC_ALLOW or CC_DENY
*/
@@ -127,12 +127,6 @@ struct CoreExport ConnectClass : public classbase
*/
unsigned long limit;
- /** Reference counter.
- * This will be 1 if no users are connected, as long as it is a valid connect block
- * When it reaches 0, the object should be deleted
- */
- unsigned long RefCount;
-
/** Create a new connect class with no settings.
*/
ConnectClass(char type, const std::string& mask);
@@ -206,7 +200,7 @@ typedef std::vector< std::pair<irc::string, time_t> > InvitedList;
/** Holds a complete list of all allow and deny tags from the configuration file (connection classes)
*/
-typedef std::vector<ConnectClass*> ClassVector;
+typedef std::vector<reference<ConnectClass> > ClassVector;
/** Typedef for the list of user-channel records for a user
*/
@@ -274,9 +268,8 @@ class CoreExport User : public StreamSocket
static LocalStringExt OperQuit;
/** Contains a pointer to the connect class a user is on from - this will be NULL for remote connections.
- * The pointer is guarenteed to *always* be valid. :)
*/
- ConnectClass *MyClass;
+ reference<ConnectClass> MyClass;
/** Hostname of connection.
* This should be valid as per RFC1035.
@@ -869,7 +862,7 @@ class CoreExport User : public StreamSocket
/** Default destructor
*/
virtual ~User();
- virtual void cull();
+ virtual bool cull();
};
/** Derived from Resolver, and performs user forward/reverse lookups.
diff --git a/src/base.cpp b/src/base.cpp
index 76e469482..930792854 100644
--- a/src/base.cpp
+++ b/src/base.cpp
@@ -26,65 +26,26 @@ classbase::classbase()
{
}
-void classbase::cull()
+bool classbase::cull()
{
+ return true;
}
classbase::~classbase()
{
}
-void BoolSet::Set(int number)
-{
- this->bits |= bitfields[number];
-}
-
-void BoolSet::Unset(int number)
-{
- this->bits &= inverted_bitfields[number];
-}
-
-void BoolSet::Invert(int number)
-{
- this->bits ^= bitfields[number];
-}
-
-bool BoolSet::Get(int number)
+refcountbase::refcountbase() : refcount(0)
{
- return ((this->bits | bitfields[number]) > 0);
}
-bool BoolSet::operator==(BoolSet other)
+bool refcountbase::cull()
{
- return (this->bits == other.bits);
+ return (refcount == 0);
}
-BoolSet BoolSet::operator|(BoolSet other)
+refcountbase::~refcountbase()
{
- BoolSet x(this->bits | other.bits);
- return x;
-}
-
-BoolSet BoolSet::operator&(BoolSet other)
-{
- BoolSet x(this->bits & other.bits);
- return x;
-}
-
-BoolSet::BoolSet()
-{
- this->bits = 0;
-}
-
-BoolSet::BoolSet(char bitmask)
-{
- this->bits = bitmask;
-}
-
-bool BoolSet::operator=(BoolSet other)
-{
- this->bits = other.bits;
- return true;
}
ExtensionItem::ExtensionItem(const std::string& Key, Module* mod) : key(Key), owner(mod)
diff --git a/src/configreader.cpp b/src/configreader.cpp
index 21bfce3db..86d0b3c5e 100644
--- a/src/configreader.cpp
+++ b/src/configreader.cpp
@@ -727,11 +727,6 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
Classes[i] = me;
}
}
-
- for(ClassMap::iterator toRemove = oldBlocksByMask.begin(); toRemove != oldBlocksByMask.end(); toRemove++)
- {
- removed_classes.push_back(toRemove->second);
- }
}
@@ -1143,9 +1138,6 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
// write once here, to try it out and make sure its ok
ServerInstance->WritePID(this->PID);
- FailedPortList pl;
- ServerInstance->BindPorts(pl);
-
/*
* These values can only be set on boot. Keep their old values. Do it before we send messages so we actually have a servername.
*/
@@ -1153,18 +1145,23 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
{
memcpy(this->ServerName, old->ServerName, sizeof(this->ServerName));
memcpy(this->sid, old->sid, sizeof(this->sid));
- }
-
- if (pl.size())
- {
- errstr << "Not all your client ports could be bound.\nThe following port(s) failed to bind:\n";
+ this->argv = old->argv;
+ this->argc = old->argc;
- int j = 1;
- for (FailedPortList::iterator i = pl.begin(); i != pl.end(); i++, j++)
+ // Same for ports... they're bound later on first run.
+ FailedPortList pl;
+ ServerInstance->BindPorts(pl);
+ if (pl.size())
{
- char buf[MAXBUF];
- snprintf(buf, MAXBUF, "%d. Address: %s Reason: %s\n", j, i->first.empty() ? "<all>" : i->first.c_str(), i->second.c_str());
- errstr << buf;
+ errstr << "Not all your client ports could be bound.\nThe following port(s) failed to bind:\n";
+
+ int j = 1;
+ for (FailedPortList::iterator i = pl.begin(); i != pl.end(); i++, j++)
+ {
+ char buf[MAXBUF];
+ snprintf(buf, MAXBUF, "%d. Address: %s Reason: %s\n", j, i->first.empty() ? "<all>" : i->first.c_str(), i->second.c_str());
+ errstr << buf;
+ }
}
}
@@ -1212,12 +1209,6 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
return;
ApplyModules(user);
- for (std::vector<ConnectClass*>::iterator i = removed_classes.begin(); i != removed_classes.end(); i++)
- {
- ConnectClass* c = *i;
- if (0 == --c->RefCount)
- delete c;
- }
}
void ServerConfig::ApplyModules(User* user)
diff --git a/src/cull_list.cpp b/src/cull_list.cpp
index 5715c3147..02776aff8 100644
--- a/src/cull_list.cpp
+++ b/src/cull_list.cpp
@@ -24,8 +24,8 @@ void CullList::Apply()
{
ServerInstance->Logs->Log("CULLLIST", DEBUG, "Deleting %s @%p", typeid(*c).name(),
(void*)c);
- c->cull();
- delete c;
+ if (c->cull())
+ delete c;
}
else
{
diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp
index 062f6b644..ebf6e3b9d 100644
--- a/src/inspsocket.cpp
+++ b/src/inspsocket.cpp
@@ -139,9 +139,10 @@ void StreamSocket::Close()
errno = save;
}
-void StreamSocket::cull()
+bool StreamSocket::cull()
{
Close();
+ return true;
}
bool StreamSocket::GetNextLine(std::string& line, char delim)
diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp
index db40c7f6a..501baa290 100644
--- a/src/modules/m_spanningtree/main.cpp
+++ b/src/modules/m_spanningtree/main.cpp
@@ -939,9 +939,9 @@ void ModuleSpanningTree::OnEvent(Event* event)
}
}
-void ModuleSpanningTree::cull()
+bool ModuleSpanningTree::cull()
{
- Utils->cull();
+ return Utils->cull();
}
ModuleSpanningTree::~ModuleSpanningTree()
diff --git a/src/modules/m_spanningtree/main.h b/src/modules/m_spanningtree/main.h
index 6e3f62056..429c0d4bd 100644
--- a/src/modules/m_spanningtree/main.h
+++ b/src/modules/m_spanningtree/main.h
@@ -191,7 +191,7 @@ class ModuleSpanningTree : public Module
void OnEvent(Event* event);
void OnLoadModule(Module* mod,const std::string &name);
void OnUnloadModule(Module* mod,const std::string &name);
- void cull();
+ bool cull();
~ModuleSpanningTree();
Version GetVersion();
void Prioritize();
diff --git a/src/modules/m_spanningtree/utils.cpp b/src/modules/m_spanningtree/utils.cpp
index fc5356c66..6f94ead60 100644
--- a/src/modules/m_spanningtree/utils.cpp
+++ b/src/modules/m_spanningtree/utils.cpp
@@ -157,7 +157,7 @@ SpanningTreeUtilities::SpanningTreeUtilities(ModuleSpanningTree* C) : Creator(C)
this->ReadConfiguration(true);
}
-void SpanningTreeUtilities::cull()
+bool SpanningTreeUtilities::cull()
{
for (unsigned int i = 0; i < Bindings.size(); i++)
{
@@ -175,7 +175,9 @@ void SpanningTreeUtilities::cull()
}
ServerUser->uuid = TreeRoot->GetID();
- ServerUser->cull();
+ if (ServerUser->cull())
+ delete ServerUser;
+ return true;
}
SpanningTreeUtilities::~SpanningTreeUtilities()
@@ -186,7 +188,6 @@ SpanningTreeUtilities::~SpanningTreeUtilities()
}
delete TreeRoot;
- delete ServerUser;
}
void SpanningTreeUtilities::AddThisServer(TreeServer* server, TreeServerList &list)
diff --git a/src/modules/m_spanningtree/utils.h b/src/modules/m_spanningtree/utils.h
index 1de6de076..d1922ed75 100644
--- a/src/modules/m_spanningtree/utils.h
+++ b/src/modules/m_spanningtree/utils.h
@@ -166,7 +166,7 @@ class SpanningTreeUtilities : public classbase
/** Prepare for class destruction
*/
- void cull();
+ bool cull();
/** Destroy class and free listeners etc
*/
diff --git a/src/users.cpp b/src/users.cpp
index f5eeff942..236df2d65 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -568,14 +568,14 @@ void User::OnError(BufferedSocketError)
ServerInstance->Users->QuitUser(this, getError());
}
-void User::cull()
+bool User::cull()
{
if (!quitting)
ServerInstance->Users->QuitUser(this, "Culled without QuitUser");
if (uuid.empty())
{
ServerInstance->Logs->Log("USERS", DEBUG, "User culled twice? UUID empty");
- return;
+ return true;
}
PurgeEmptyChannels();
if (IS_LOCAL(this))
@@ -590,14 +590,6 @@ void User::cull()
ServerInstance->Logs->Log("USERS", DEBUG, "Failed to remove user from vector");
}
- if (this->MyClass)
- {
- this->MyClass->RefCount--;
- ServerInstance->Logs->Log("USERS", DEBUG, "User destructor -- connect refcount now: %lu", this->MyClass->RefCount);
- if (MyClass->RefCount == 0)
- delete MyClass;
- }
-
if (this->AllowedOperCommands)
{
delete AllowedOperCommands;
@@ -618,6 +610,7 @@ void User::cull()
ServerInstance->Users->uuidlist->erase(uuid);
uuid.clear();
+ return true;
}
void User::Oper(const std::string &opertype, const std::string &opername)
@@ -1658,7 +1651,7 @@ ConnectClass* User::SetClass(const std::string &explicit_name)
* deny change if change will take class over the limit check it HERE, not after we found a matching class,
* because we should attempt to find another class if this one doesn't match us. -- w00t
*/
- if (c->limit && (c->RefCount >= c->limit))
+ if (c->limit && (c->GetReferenceCount() >= c->limit))
{
ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "OOPS: Connect class limit (%lu) hit, denying", c->limit);
continue;
@@ -1688,20 +1681,7 @@ ConnectClass* User::SetClass(const std::string &explicit_name)
*/
if (found)
{
- /* only fiddle with refcounts if they are already in a class .. */
- if (this->MyClass)
- {
- if (found == this->MyClass) // no point changing this shit :P
- return this->MyClass;
- this->MyClass->RefCount--;
- ServerInstance->Logs->Log("USERS", DEBUG, "Untying user from connect class -- refcount: %lu", this->MyClass->RefCount);
- if (MyClass->RefCount == 0)
- delete MyClass;
- }
-
- this->MyClass = found;
- this->MyClass->RefCount++;
- ServerInstance->Logs->Log("USERS", DEBUG, "User tied to new class -- connect refcount now: %lu", this->MyClass->RefCount);
+ MyClass = found;
}
return this->MyClass;
@@ -1824,8 +1804,7 @@ const std::string FakeUser::GetFullRealHost()
ConnectClass::ConnectClass(char t, const std::string& mask)
: type(t), name("unnamed"), registration_timeout(0), host(mask),
pingtime(0), pass(""), hash(""), softsendqmax(0), hardsendqmax(0),
- recvqmax(0), maxlocal(0), maxglobal(0), maxchans(0), port(0), limit(0),
- RefCount(1)
+ recvqmax(0), maxlocal(0), maxglobal(0), maxchans(0), port(0), limit(0)
{
}
@@ -1836,7 +1815,7 @@ ConnectClass::ConnectClass(char t, const std::string& mask, const ConnectClass&
softsendqmax(parent.softsendqmax), hardsendqmax(parent.hardsendqmax),
recvqmax(parent.recvqmax), maxlocal(parent.maxlocal),
maxglobal(parent.maxglobal), maxchans(parent.maxchans),
- port(parent.port), limit(parent.limit), RefCount(1)
+ port(parent.port), limit(parent.limit)
{
}