1 /*
2
3 *************************************************************************
4
5 ArmageTron -- Just another Tron Lightcycle Game in 3D.
6 Copyright (C) 2000 Manuel Moos (manuel@moosnet.de)
7
8 **************************************************************************
9
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 ***************************************************************************
25
26 */
27
28 #ifndef ArmageTron_SAFEPTR_H
29 #define ArmageTron_SAFEPTR_H
30
31 #include "config.h"
32 #include <stddef.h>
33 #if HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 #include "tError.h"
38
39 class tCheckedPTRBase{
40 friend class tPTRList;
41 int id;
42 protected:
43 void *target;
44 public:
45 tCheckedPTRBase(void *x);
46 tCheckedPTRBase(const tCheckedPTRBase &x);
47 tCheckedPTRBase();
48 ~tCheckedPTRBase();
49
50 tCheckedPTRBase& operator=(void *x){target=x; return *this;}
51 // void * operator->() const {return target;}
52 // void & operator*() const {return *target;}
53 //operator void *() const {return target;}
54 operator bool() const{return target!=NULL;}
55 bool operator !() const{return !target;}
56
57 static void CheckDestructed(void *test);
58
59 static void Check();
60 };
61
62
63 template<class T> class tCheckedPTR:public tCheckedPTRBase{
64 typedef T myclass;
65 public:
tCheckedPTR(T * x)66 tCheckedPTR(T *x):tCheckedPTRBase(x){}
tCheckedPTR(const tCheckedPTR<T> & x)67 tCheckedPTR(const tCheckedPTR<T> &x):tCheckedPTRBase(x.target){}
tCheckedPTR()68 tCheckedPTR():tCheckedPTRBase(){}
~tCheckedPTR()69 ~tCheckedPTR(){}
70
71 tCheckedPTR<T> &operator=(T *x){tCheckedPTRBase::operator=(x); return *this;}
72 tCheckedPTR<T> &operator=(const tCheckedPTR<T> &x)
73 {tCheckedPTRBase::operator=(x.target); return *this;}
74 T * operator->() const {return reinterpret_cast<T*>(target);}
75 T & operator*() const {return *reinterpret_cast<T*>(target);}
76 operator T*() const {return reinterpret_cast<T*>(target);}
77 // T** operator&() {return reinterpret_cast<T **>(&target);}
78
79 bool operator==(const T* x)const{return target==x;}
80 bool operator!=(const T* x)const{return target!=x;}
81 bool operator==(const tCheckedPTR<T> &x)const{return target==x.target;}
82 bool operator!=(const tCheckedPTR<T> &x)const{return target!=x.target;}
83
Destroy()84 void Destroy(){
85 if (target){
86 T *dummy=reinterpret_cast<T*>(target);
87 target=NULL;
88 delete dummy;
89 }
90 }
91 };
92
93 template<class T> class tCheckedPTRConst:public tCheckedPTRBase{
94 typedef T myclass;
95 public:
tCheckedPTRConst()96 tCheckedPTRConst():tCheckedPTRBase(NULL){}
tCheckedPTRConst(const T * x)97 tCheckedPTRConst(const T *x):tCheckedPTRBase(reinterpret_cast<void *>(x)){}
tCheckedPTRConst(const tCheckedPTRConst<T> & x)98 tCheckedPTRConst(const tCheckedPTRConst<T> &x):tCheckedPTRBase(x.target){}
tCheckedPTRConst(const tCheckedPTR<T> & x)99 tCheckedPTRConst(const tCheckedPTR<T> &x):tCheckedPTRBase(x.operator->()){}
~tCheckedPTRConst()100 ~tCheckedPTRConst(){}
101
102 tCheckedPTRConst<T> &operator=(const T *x)
103 {tCheckedPTRBase::operator=(reinterpret_cast<T *>(x)); return *this;}
104 tCheckedPTRConst<T> &operator=(const tCheckedPTRConst<T> &x)
105 {tCheckedPTRBase::operator=(x.target); return *this;}
106 tCheckedPTRConst<T> &operator=(const tCheckedPTR<T> &x)
107 {tCheckedPTRBase::operator=(x.operator->()); return *this;}
108
109 const T * operator->() const {return target;}
110 const T & operator*() const {return *reinterpret_cast<T*>(target);}
111 operator const T*() const {return reinterpret_cast<const T*>(target);}
112 // const T** operator&() {return reinterpret_cast<const T **>(&target);}
113
114 bool operator==(const T* x)const{return target==x;}
115 bool operator!=(const T* x)const{return target!=x;}
116
Destroy()117 void Destroy(){
118 if (target){
119 T *dummy=reinterpret_cast<T *>(target);
120 target=NULL;
121 dummy->AddRef();
122 dummy->Release();
123 }
124 }
125 };
126
127
128
129
130 //#define CHECK_PTR 1
131
132
SafeDelete(T & x)133 template<class T> void SafeDelete(T &x){
134 x.Destroy();
135 }
136
SafeDeletePtr(T * & x)137 template<class T> void SafeDeletePtr(T * &x){
138 if (x){
139 T *dummy=x;
140 x=NULL;
141 delete dummy;
142 }
143 }
144
145 #define tDESTROY_PTR(x) SafeDeletePtr(x)
146
147 #ifdef DEBUG
148 #ifdef CHECK_PTR
149 #define tDESTROY(x) SafeDelete(x)
150 #define tCHECKED_PTR(x) tCheckedPTR<x>
151 #define tCHECKED_PTR_CONST(x) tCheckedPTRConst<x>
152 #define tCHECK_DEST tCheckedPTRBase::CheckDestructed(this)
153 #define tSAFEPTR
154 #else
155 #define tDESTROY(x) SafeDeletePtr(x)
156 #define tCHECK_DEST
157 #define tCHECKED_PTR(x) x *
158 #define tCHECKED_PTR_CONST(x) const x *
159 #endif
160 #else
161 #define tDESTROY(x) SafeDeletePtr(x)
162 #define tCHECK_DEST
163 #define tCHECKED_PTR(x) x *
164 #define tCHECKED_PTR_CONST(x) const x *
165 #endif
166
167 #define tCONTROLLED_PTR(x) tControlledPTR<x>
168
169
170
171 template<class T> class tControlledPTR{
172 tCHECKED_PTR(T) target;
173
AddRef()174 void AddRef(){
175 if (target)
176 target->AddRef();
177 }
178
Release()179 void Release(){
180 if (target){
181 //#ifdef tSAFEPTR
182 T *dummy=reinterpret_cast<T*>(target);
183 target=NULL;
184 dummy->Release();
185 //#else
186 // target->Release();
187 // target=NULL;
188 //#endif
189 }
190 }
191
192 public:
193
tControlledPTR(T * x)194 tControlledPTR(T *x):target(x){AddRef();}
tControlledPTR(const tCheckedPTR<T> & x)195 tControlledPTR(const tCheckedPTR<T> &x):target(x.operator->()){AddRef();}
tControlledPTR(const tControlledPTR<T> & x)196 tControlledPTR(const tControlledPTR<T> &x):target(x.target){AddRef();}
tControlledPTR()197 tControlledPTR():target(NULL){}
198
199
200 tControlledPTR<T> &operator=(T *x){
201 if (target!=x){
202 Release();
203 target=x;
204 AddRef();
205 }
206 return *this;
207 }
208
209 tControlledPTR<T> &operator=(const tControlledPTR<T> &x){
210 if (target!=x.target){
211 Release();
212 target=x.target;
213 AddRef();
214 }
215 return *this;
216 }
217
218 T * operator->() const {
219 return target;
220 }
221
222 T & operator*() const {
223 return *target;
224 }
225
226 operator T*() const {
227 return target;
228 }
229
230 /*
231 T** operator&() {
232 return ⌖
233 }
234 */
235
236 bool operator==(const T* x)const{
237 return target==x;
238 }
239
240 bool operator!=(const T* x)const{
241 return target!=x;
242 }
243
244 bool operator==(T* x)const{
245 return target==x;
246 }
247
248 bool operator!=(T* x)const{
249 return target!=x;
250 }
251
252 operator bool()const{
253 return target!=NULL;
254 }
255
256 bool operator !()const{
257 return target==NULL;
258 }
259
260 bool operator==(const tControlledPTR<T> &x)const{
261 return target==x.target;
262 }
263
264 bool operator!=(const tControlledPTR<T> &x)const{
265 return target!=x.target;
266 }
267
Destroy()268 void Destroy(){
269 if (target){
270 #ifdef tSAFEPTR
271 T *dummy=(T *)target;
272 target=NULL;
273 delete dummy;
274 #else
275 delete target();
276 target=NULL;
277 #endif
278 }
279 }
280
281
~tControlledPTR()282 ~tControlledPTR(){
283 Release();
284 }
285 };
286
287 template<class T> class tJUST_CONTROLLED_PTR{
288 T * target;
289
AddRef()290 void AddRef(){
291 if (target)
292 target->AddRef();
293 }
294
Release()295 void Release(){
296 if (target){
297 T *dummy=target;
298 target=NULL;
299 dummy->Release();
300 }
301 }
302
303 public:
304
tJUST_CONTROLLED_PTR(T * x)305 tJUST_CONTROLLED_PTR(T *x):target(x){AddRef();}
tJUST_CONTROLLED_PTR(const tCheckedPTR<T> & x)306 tJUST_CONTROLLED_PTR(const tCheckedPTR<T> &x):target(x.operator->()){AddRef();}
tJUST_CONTROLLED_PTR(const tJUST_CONTROLLED_PTR<T> & x)307 tJUST_CONTROLLED_PTR(const tJUST_CONTROLLED_PTR<T> &x):target(x.target){AddRef();}
tJUST_CONTROLLED_PTR()308 tJUST_CONTROLLED_PTR():target(NULL){}
309
310
311 tJUST_CONTROLLED_PTR<T> &operator=(T *x){
312 if (target!=x){
313 Release();
314 target=x;
315 AddRef();
316 }
317 return *this;
318 }
319
320 tJUST_CONTROLLED_PTR<T> &operator=(const tJUST_CONTROLLED_PTR<T> &x){
321 operator=(x.target);
322 return *this;
323 }
324
325 T * operator->() const {
326 return target;
327 }
328
329 T & operator*() const {
330 return *target;
331 }
332
333 operator T*() const {
334 return target;
335 }
336
337 /*
338 T** operator&() {
339 return ⌖
340 }
341 */
342
343 bool operator==(const T* x)const{
344 return target==x;
345 }
346
347 bool operator!=(const T* x)const{
348 return target!=x;
349 }
350
351 bool operator==(const tJUST_CONTROLLED_PTR<T> &x)const{
352 return target==x.target;
353 }
354
355 bool operator!=(const tJUST_CONTROLLED_PTR<T> &x)const{
356 return target!=x.target;
357 }
358
Destroy()359 void Destroy(){
360 if (target){
361 #ifdef tSAFEPTR
362 T *dummy=(T *)target;
363 target=NULL;
364 delete dummy;
365 #else
366 delete target();
367 target=NULL;
368 #endif
369 }
370 }
371
372
~tJUST_CONTROLLED_PTR()373 ~tJUST_CONTROLLED_PTR(){
374 Release();
375 }
376 };
377
378
379 template<class T> bool operator==(const T *x, const tJUST_CONTROLLED_PTR<T> &y)
380 {
381 return (x == static_cast<const T*>(y));
382 }
383
384 template<class T> bool operator==(T *x, const tJUST_CONTROLLED_PTR<T> &y)
385 {
386 return (x == static_cast<const T*>(y));
387 }
388
389 template<class T> bool operator==(const T *x, tJUST_CONTROLLED_PTR<T> &y)
390 {
391 return (x == static_cast<const T*>(y));
392 }
393
394 template<class T> bool operator==(T *x, tJUST_CONTROLLED_PTR<T> &y)
395 {
396 return (x == static_cast<const T*>(y));
397 }
398
399 template< class T > class tStackObject: public T
400 {
401 public:
tStackObject()402 tStackObject(){ this->AddRef(); }
403 template< typename A >
tStackObject(A & a)404 explicit tStackObject( A& a ): T( a ) { this->AddRef(); }
405 template< typename A, typename B >
tStackObject(A & a,B & b)406 tStackObject( A& a, B& b ): T( a, b ) { this->AddRef(); }
407 template< typename A, typename B, typename C >
tStackObject(A & a,B & b,C & c)408 tStackObject( A& a, B& b, C& c ): T( a, b, c ) { this->AddRef(); }
409
~tStackObject()410 ~tStackObject()
411 {
412 if ( this->GetRefcount() != 1 )
413 st_Breakpoint();
414
415 this->refCtr_ = -1000;
416 }
417 };
418
419 #ifdef DEBUG
420 void st_AddRefBreakpint( void const * object );
421 void st_ReleaseBreakpint( void const * object );
422 #endif
423
424 // not thread-safe mutex
425 struct tNonMutex
426 {
acquiretNonMutex427 void acquire(){}
releasetNonMutex428 void release(){}
429 };
430
431 template< class T, class MUTEX = tNonMutex > class tReferencable
432 {
433 friend class tStackObject< T >;
434
435 public:
tReferencable()436 tReferencable() :refCtr_(0) {}
tReferencable(const tReferencable &)437 tReferencable ( const tReferencable& ) :refCtr_(0) {}
438 tReferencable& operator = ( const tReferencable& ){ return *this; }
439
AddRef()440 void AddRef () const
441 {
442 #ifdef DEBUG
443 st_AddRefBreakpint( this );
444 #endif
445 tASSERT_THIS();
446 tASSERT( refCtr_ >= 0 );
447 mutex_.acquire();
448 ++refCtr_;
449 mutex_.release();
450 tASSERT( refCtr_ >= 0 );
451 }
452
Release()453 void Release () const
454 {
455 #ifdef DEBUG
456 st_ReleaseBreakpint( this );
457 #endif
458
459 tASSERT_THIS();
460 tASSERT ( refCtr_ >= 0 );
461 mutex_.acquire();
462 --refCtr_;
463 bool kill = (refCtr_ <= 0);
464 mutex_.release();
465
466 if ( kill )
467 {
468 refCtr_ = -1000;
469 delete static_cast< const T* >( this );
470 }
471 }
472
GetRefcount()473 int GetRefcount () const
474 {
475 tASSERT_THIS();
476 return refCtr_;
477 }
478 protected:
~tReferencable()479 ~tReferencable()
480 {
481 tASSERT_THIS();
482 tASSERT( ( refCtr_ == -1000 || refCtr_ == 0 ) );
483 refCtr_ = -1000;
484 }
485 private:
486 mutable int refCtr_;
487 mutable MUTEX mutex_;
488 };
489
490
491 #endif
492
493
494
495