anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

base.h (3109B)

      1 /*
      2  *
      3  * (C) 2008-2011 Adam <Adam@anope.org>
      4  * (C) 2008-2022 Anope Team <team@anope.org>
      5  *
      6  * Please read COPYING and README for further details.
      7  */
      8 
      9 #ifndef BASE_H
     10 #define BASE_H
     11 
     12 #include "services.h"
     13 
     14 /** The base class that most classes in Anope inherit from
     15  */
     16 class CoreExport Base
     17 {
     18 	/* References to this base class */
     19 	std::set<ReferenceBase *> *references;
     20  public:
     21 	Base();
     22 	virtual ~Base();
     23 
     24 	/** Adds a reference to this object. Eg, when a Reference
     25 	 * is created referring to this object this is called. It is used to
     26 	 * cleanup references when this object is destructed.
     27 	 */
     28 	void AddReference(ReferenceBase *r);
     29 
     30 	void DelReference(ReferenceBase *r);
     31 };
     32 
     33 class ReferenceBase
     34 {
     35  protected:
     36 	bool invalid;
     37  public:
     38 	ReferenceBase() : invalid(false) { }
     39 	ReferenceBase(const ReferenceBase &other) : invalid(other.invalid) { }
     40 	virtual ~ReferenceBase() { }
     41 	inline void Invalidate() { this->invalid = true; }
     42 };
     43 
     44 /** Used to hold pointers to objects that may be deleted. A Reference will
     45  * no longer be valid once the object it refers is destructed.
     46  */
     47 template<typename T>
     48 class Reference : public ReferenceBase
     49 {
     50  protected:
     51 	T *ref;
     52  public:
     53 	Reference() : ref(NULL)
     54 	{
     55 	}
     56 
     57 	Reference(T *obj) : ref(obj)
     58 	{
     59 		if (ref)
     60 			ref->AddReference(this);
     61 	}
     62 
     63 	Reference(const Reference<T> &other) : ReferenceBase(other), ref(other.ref)
     64 	{
     65 		if (operator bool())
     66 			ref->AddReference(this);
     67 	}
     68 
     69 	virtual ~Reference()
     70 	{
     71 		if (operator bool())
     72 			ref->DelReference(this);
     73 	}
     74 
     75 	inline Reference<T>& operator=(const Reference<T> &other)
     76 	{
     77 		if (this != &other)
     78 		{
     79 			if (*this)
     80 				this->ref->DelReference(this);
     81 
     82 			this->ref = other.ref;
     83 			this->invalid = other.invalid;
     84 
     85 			if (*this)
     86 				this->ref->AddReference(this);
     87 		}
     88 		return *this;
     89 	}
     90 
     91 	/* We explicitly call operator bool here in several places to prevent other
     92 	 * operators, such operator T*, from being called instead, which will mess
     93 	 * with any class inheriting from this that overloads this operator.
     94 	 */
     95 	virtual operator bool()
     96 	{
     97 		if (!this->invalid)
     98 			return this->ref != NULL;
     99 		return false;
    100 	}
    101 
    102 	inline operator T*()
    103 	{
    104 		if (operator bool())
    105 			return this->ref;
    106 		return NULL;
    107 	}
    108 
    109 	inline T* operator->()
    110 	{
    111 		if (operator bool())
    112 			return this->ref;
    113 		return NULL;
    114 	}
    115 
    116 	inline T* operator*()
    117 	{
    118 		if (operator bool())
    119 			return this->ref;
    120 		return NULL;
    121 	}
    122 
    123 	/** Note that we can't have an operator< that returns this->ref < other.ref
    124 	 * because this function is used to sort objects in containers (such as set
    125 	 * or map), and if the references themselves can change if the object they
    126 	 * refer to is invalidated or changed, then this screws with the order that
    127 	 * the objects would be in the container without properly adjusting the
    128 	 * container, resulting in weird stuff.
    129 	 *
    130 	 * As such, we don't allow storing references in containers that require
    131 	 * operator<, because they would not be able to compare what the references
    132 	 * actually referred to.
    133 	 */
    134 
    135 	inline bool operator==(const Reference<T> &other)
    136 	{
    137 		if (!this->invalid)
    138 			return this->ref == other;
    139 		return false;
    140 	}
    141 };
    142 
    143 #endif // BASE_H