From fa2cdd0bb89330cfd9a6c49c4705da2a3cb02834 Mon Sep 17 00:00:00 2001 From: danieldg Date: Sun, 25 Oct 2009 20:03:55 +0000 Subject: Force heap allocation of refcountbase, create usecountbase for non-allocation reference counting git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11978 e03df62e-2008-0410-955e-edbf42e46eb7 --- include/base.h | 59 ++++++++++++++++++--------------------------- include/extensible.h | 2 +- include/inspsocket.h | 4 +-- include/modules.h | 4 +-- src/base.cpp | 29 +++++++++------------- src/inspircd.cpp | 4 ++- src/modules.cpp | 4 +-- src/modules/m_showwhois.cpp | 2 +- 8 files changed, 45 insertions(+), 63 deletions(-) diff --git a/include/base.h b/include/base.h index b39c7d077..bc096b85b 100644 --- a/include/base.h +++ b/include/base.h @@ -81,35 +81,46 @@ class CoreExport refcountbase refcountbase(); virtual ~refcountbase(); inline unsigned int GetReferenceCount() const { return refcount; } - friend class reference_base; void* operator new(size_t); void operator delete(void*); + inline void refcount_inc() const { refcount++; } + inline bool refcount_dec() const { refcount--; return !refcount; } private: // uncopyable refcountbase(const refcountbase&); void operator=(const refcountbase&); }; -class CoreExport reference_base +/** Base class for use count tracking. Uses reference<>, but does not + * cause object deletion when the last user is removed. + */ +class CoreExport usecountbase { - protected: - template static inline unsigned int inc(T* v) { return ++(v->refcount); } - template static inline unsigned int dec(T* v) { return --(v->refcount); } - + mutable unsigned int usecount; + public: + usecountbase() : usecount(0) { } + ~usecountbase(); + inline unsigned int GetUseCount() const { return usecount; } + inline void refcount_inc() const { usecount++; } + inline bool refcount_dec() const { usecount--; return false; } + private: + // uncopyable + usecountbase(const usecountbase&); + void operator=(const usecountbase&); }; template -class reference : public reference_base +class reference { 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* v) : value(v) { if (value) value->refcount_inc(); } + reference(const reference& v) : value(v.value) { if (value) value->refcount_inc(); } reference& operator=(const reference& other) { if (other.value) - inc(other.value); + other.value->refcount_inc(); this->reference::~reference(); value = other.value; return *this; @@ -117,12 +128,8 @@ class reference : public reference_base ~reference() { - if (value) - { - int rc = dec(value); - if (rc == 0) - delete value; - } + if (value && value->refcount_dec()) + delete value; } inline operator bool() const { return value; } inline operator T*() const { return value; } @@ -130,8 +137,6 @@ class reference : public reference_base inline T& operator*() const { return *value; } inline bool operator<(const reference& other) const { return value < other.value; } inline bool operator>(const reference& other) const { return value > other.value; } - inline bool operator==(const reference& other) const { return value == other.value; } - inline bool operator!=(const reference& other) const { return value != other.value; } private: void* operator new(size_t); void operator delete(void*); @@ -190,22 +195,6 @@ class CoreExport ModuleException : public CoreException ModuleException(const std::string &message, Module* me = NULL); }; -/** Module reference, similar to reference - */ -class CoreExport ModuleRef : public reference_base -{ - Module* const value; - public: - ModuleRef(Module* v); - ~ModuleRef(); - inline operator Module*() const { return value; } - inline Module* operator->() const { return value; } - inline Module& operator*() const { return *value; } - private: - ModuleRef(const ModuleRef&); - void operator=(const ModuleRef&); - void* operator new(size_t); - void operator delete(void*); -}; +typedef const reference ModuleRef; #endif diff --git a/include/extensible.h b/include/extensible.h index 81859b1c8..487b67408 100644 --- a/include/extensible.h +++ b/include/extensible.h @@ -12,7 +12,7 @@ enum SerializeFormat /** Class represnting an extension of some object */ -class CoreExport ExtensionItem : public refcountbase +class CoreExport ExtensionItem : public usecountbase { public: const std::string key; diff --git a/include/inspsocket.h b/include/inspsocket.h index 3e5c75235..8172338ac 100644 --- a/include/inspsocket.h +++ b/include/inspsocket.h @@ -94,7 +94,7 @@ class CoreExport SocketTimeout : public Timer class CoreExport StreamSocket : public EventHandler { /** Module that handles raw I/O for this socket, or NULL */ - Module *IOHook; + reference IOHook; /** Private send queue. Note that individual strings may be shared */ std::deque sendq; @@ -105,7 +105,7 @@ class CoreExport StreamSocket : public EventHandler protected: std::string recvq; public: - StreamSocket() : IOHook(NULL), sendq_len(0) {} + StreamSocket() : sendq_len(0) {} inline Module* GetIOHook() { return IOHook; } inline void AddIOHook(Module* m) { IOHook = m; } inline void DelIOHook() { IOHook = NULL; } diff --git a/include/modules.h b/include/modules.h index 8bda9a725..26c4ef466 100644 --- a/include/modules.h +++ b/include/modules.h @@ -298,10 +298,8 @@ enum Implementation * its methods will be called when irc server events occur. class inherited from module must be * instantiated by the ModuleFactory class (see relevent section) for the module to be initialised. */ -class CoreExport Module : public classbase +class CoreExport Module : public classbase, public usecountbase { - unsigned int refcount; - friend class reference_base; public: /** File that this module was loaded from */ diff --git a/src/base.cpp b/src/base.cpp index bf4232754..8e81f7b73 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -43,7 +43,6 @@ CullResult::CullResult() // This trick detects heap allocations of refcountbase objects static void* last_heap = NULL; -static const unsigned int top_bit = 1 << (8*sizeof(unsigned int) - 1); void* refcountbase::operator new(size_t size) { @@ -58,21 +57,26 @@ void refcountbase::operator delete(void* obj) ::operator delete(obj); } -refcountbase::refcountbase() +refcountbase::refcountbase() : refcount(0) { - if (this == last_heap) - refcount = 0; - else - refcount = top_bit; + if (this != last_heap) + throw CoreException("Reference allocate on the stack!"); } refcountbase::~refcountbase() { - if ((refcount & ~top_bit) && ServerInstance && ServerInstance->Logs) - ServerInstance->Logs->Log("CULLLIST", DEBUG, "refcountbase::~ @%p with refcount %x", + if (refcount && ServerInstance && ServerInstance->Logs) + ServerInstance->Logs->Log("CULLLIST", DEBUG, "refcountbase::~ @%p with refcount %d", (void*)this, refcount); } +usecountbase::~usecountbase() +{ + if (usecount && ServerInstance && ServerInstance->Logs) + ServerInstance->Logs->Log("CULLLIST", DEBUG, "usecountbase::~ @%p with refcount %d", + (void*)this, usecount); +} + ExtensionItem::ExtensionItem(const std::string& Key, Module* mod) : key(Key), owner(mod) { } @@ -297,12 +301,3 @@ ModuleException::ModuleException(const std::string &message, Module* who) { } -ModuleRef::ModuleRef(Module* v) : value(v) -{ - if (value) inc(value); -} - -ModuleRef::~ModuleRef() -{ - if (value) dec(value); -} diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 58480668b..b67815ed2 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -113,6 +113,8 @@ void InspIRCd::Cleanup() /* Must be deleted before modes as it decrements modelines */ if (FakeClient) FakeClient->cull(); + if (Res) + Res->cull(); DeleteZero(this->FakeClient); DeleteZero(this->Users); DeleteZero(this->Modes); @@ -523,7 +525,7 @@ InspIRCd::InspIRCd(int argc, char** argv) : this->Config->Apply(NULL, ""); Logs->OpenFileLogs(); - this->Res = new DNS; + this->Res = new DNS(); /* * Initialise SID/UID. diff --git a/src/modules.cpp b/src/modules.cpp index a1c53a1e8..b3aabf284 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -51,15 +51,13 @@ void Event::Send() // These declarations define the behavours of the base class Module (which does nothing at all) -Module::Module() : refcount(1) { } +Module::Module() { } CullResult Module::cull() { return classbase::cull(); } Module::~Module() { - if (refcount != 1) - ServerInstance->Logs->Log("MODULE", DEFAULT, "References remain to destructed module " + ModuleSourceFile); } ModResult Module::OnSendSnotice(char &snomask, std::string &type, const std::string &message) { return MOD_RES_PASSTHRU; } diff --git a/src/modules/m_showwhois.cpp b/src/modules/m_showwhois.cpp index be1871bad..074f1941c 100644 --- a/src/modules/m_showwhois.cpp +++ b/src/modules/m_showwhois.cpp @@ -110,7 +110,7 @@ class ModuleShowwhois : public Module if (!dest->IsModeSet('W') || source == dest) return; - if (!ShowWhoisFromOpers && (IS_OPER(source) != IS_OPER(dest))) + if (!ShowWhoisFromOpers && (!IS_OPER(source) != !IS_OPER(dest))) return; if (IS_LOCAL(dest)) -- cgit v1.2.3