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 &target;
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 &target;
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