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