OpenMoHAA 0.82.0
Loading...
Searching...
No Matches
safeptr.h
1/*
2===========================================================================
3Copyright (C) 2025 the OpenMoHAA team
4
5This file is part of OpenMoHAA source code.
6
7OpenMoHAA source code is free software; you can redistribute it
8and/or modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 2 of the License,
10or (at your option) any later version.
11
12OpenMoHAA source code is distributed in the hope that it will be
13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with OpenMoHAA source code; if not, write to the Free Software
19Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20===========================================================================
21*/
22
23// safeptr.h: Safe Pointers
24
25#pragma once
26
27#include "Linklist.h"
28
29#include <utility>
30
31class SafePtrBase
32{
33private:
34 void AddReference(Class *ptr);
35 void RemoveReference(Class *ptr);
36
37protected:
38 SafePtrBase *prev;
39 SafePtrBase *next;
40 Class *ptr;
41
42public:
43 SafePtrBase();
44 virtual ~SafePtrBase();
45 void InitSafePtr(Class *newptr);
46 Class *Pointer(void);
47 void Clear(void);
48
49protected:
50 void Move(SafePtrBase&& other);
51};
52
53inline void SafePtrBase::AddReference(Class *ptr)
54{
55 if (!ptr->SafePtrList) {
56 ptr->SafePtrList = this;
57 LL_Reset(this, next, prev);
58 } else {
59 LL_Add(ptr->SafePtrList, this, next, prev);
60 }
61}
62
63inline void SafePtrBase::RemoveReference(Class *ptr)
64{
65 if (ptr->SafePtrList == this) {
66 if (ptr->SafePtrList->next == this) {
67 ptr->SafePtrList = nullptr;
68 } else {
69 ptr->SafePtrList = next;
70 LL_Remove(this, next, prev);
71 }
72 } else {
73 LL_Remove(this, next, prev);
74 }
75}
76
77inline void SafePtrBase::Clear(void)
78{
79 if (ptr) {
80 RemoveReference(ptr);
81 ptr = nullptr;
82 }
83}
84
85inline SafePtrBase::SafePtrBase()
86{
87 prev = nullptr;
88 next = nullptr;
89 ptr = nullptr;
90}
91
92inline SafePtrBase::~SafePtrBase()
93{
94 Clear();
95}
96
97inline Class *SafePtrBase::Pointer(void)
98{
99 return ptr;
100}
101
102inline void SafePtrBase::InitSafePtr(Class *newptr)
103{
104 if (ptr != newptr) {
105 if (ptr) {
106 RemoveReference(ptr);
107 }
108
109 ptr = newptr;
110 if (ptr == nullptr) {
111 return;
112 }
113
114 AddReference(ptr);
115 }
116}
117
118inline void SafePtrBase::Move(SafePtrBase&& other)
119{
120 prev = other.prev;
121 next = other.next;
122 ptr = other.ptr;
123
124 if (ptr && ptr->SafePtrList) {
125 if (ptr->SafePtrList == &other) {
126 ptr->SafePtrList = this;
127 } else {
128 if (ptr->SafePtrList->prev == &other) {
129 ptr->SafePtrList->prev = this;
130 }
131 if (ptr->SafePtrList->next == &other) {
132 ptr->SafePtrList->next = this;
133 }
134 }
135 }
136
137 if (prev) {
138 if (prev == &other) {
139 prev = this;
140 } else {
141 assert(prev->next == &other || prev->next == this);
142 prev->next = this;
143 }
144 }
145 if (next) {
146 if (next == &other) {
147 next = this;
148 } else {
149 assert(next->prev == &other || next->prev == this);
150 next->prev = this;
151 }
152 }
153
154 other.next = other.prev = NULL;
155 other.ptr = NULL;
156}
157
158template<class T>
159class SafePtr : public SafePtrBase
160{
161public:
162 SafePtr(T *objptr = 0);
163 SafePtr(const SafePtr& obj);
164 SafePtr(SafePtr&& obj);
165
166 SafePtr& operator=(const SafePtr& obj);
167 SafePtr& operator=(T *const obj);
168 SafePtr& operator=(SafePtr&& obj);
169
170#ifdef LINUX
171 friend bool operator== <>(SafePtr<T> a, T *b);
172 friend bool operator!= <>(SafePtr<T> a, T *b);
173 friend bool operator== <>(T *a, SafePtr<T> b);
174 friend bool operator!= <>(T *a, SafePtr<T> b);
175 friend bool operator== <>(SafePtr<T> a, SafePtr<T> b);
176 friend bool operator!= <>(SafePtr<T> a, SafePtr<T> b);
177#else
178 // The compiler/linker gets confused when the friend functions definition are not templated
179 template<class U>
180 friend bool operator==(SafePtr<U> a, U *b);
181 template<class U>
182 friend bool operator!=(SafePtr<U> a, U *b);
183 template<class U>
184 friend bool operator==(U *a, SafePtr<U> b);
185 template<class U>
186 friend bool operator!=(U *a, SafePtr<U> b);
187 template<class U>
188 friend bool operator==(SafePtr<U> a, SafePtr<U> b);
189 template<class U>
190 friend bool operator!=(SafePtr<U> a, SafePtr<U> b);
191#endif
192
193 bool operator!() const;
194 operator T *() const;
195 T *operator->() const;
196 T& operator*() const;
197};
198
199template<class T>
200inline SafePtr<T>::SafePtr(T *objptr)
201{
202 InitSafePtr((Class *)objptr);
203}
204
205template<class T>
206inline SafePtr<T>::SafePtr(const SafePtr& obj)
207{
208 InitSafePtr(obj.ptr);
209}
210
211template<class T>
212inline SafePtr<T>::SafePtr(SafePtr&& obj)
213{
214 Move(std::move(obj));
215}
216
217template<class T>
218inline SafePtr<T>& SafePtr<T>::operator=(const SafePtr& obj)
219{
220 InitSafePtr(obj.ptr);
221 return *this;
222}
223
224template<class T>
225inline SafePtr<T>& SafePtr<T>::operator=(SafePtr&& obj)
226{
227 Clear();
228 Move(std::move(obj));
229
230 return *this;
231}
232
233template<class T>
234inline SafePtr<T>& SafePtr<T>::operator=(T *const obj)
235{
236 InitSafePtr(obj);
237 return *this;
238}
239
240template<class T>
241inline bool operator==(SafePtr<T> a, T *b)
242{
243 return a.ptr == b;
244}
245
246template<class T>
247inline bool operator!=(SafePtr<T> a, T *b)
248{
249 return a.ptr != b;
250}
251
252template<class T>
253inline bool operator==(T *a, SafePtr<T> b)
254{
255 return a == b.ptr;
256}
257
258template<class T>
259inline bool operator!=(T *a, SafePtr<T> b)
260{
261 return a != b.ptr;
262}
263
264template<class T>
265inline bool operator==(SafePtr<T> a, SafePtr<T> b)
266{
267 return a.ptr == b.ptr;
268}
269
270template<class T>
271inline bool operator!=(SafePtr<T> a, SafePtr<T> b)
272{
273 return a.ptr != b.ptr;
274}
275
276template<class T>
277inline bool SafePtr<T>::operator!() const
278{
279 return ptr == nullptr;
280}
281
282template<class T>
283inline SafePtr<T>::operator T *() const
284{
285 return (T *)ptr;
286}
287
288template<class T>
289inline T *SafePtr<T>::operator->() const
290{
291 return (T *)ptr;
292}
293
294template<class T>
295inline T& SafePtr<T>::operator*() const
296{
297 return *(T *)ptr;
298}
Definition class.h:276
Definition safeptr.h:32
Definition safeptr.h:160