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