Main Page | Compound List | File List | Compound Members

rptr.h

00001 /* -*- c++ -*- */
00002 /*
00003  * A reference-counting smart pointer template class for C++ 
00004  *
00005  * Copyright (C) 1998,2004 Oskar Enoksson (enok@lysator.liu.se)
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  
00020  */
00021 
00022 #ifndef RPTR_RPTR_HDR
00023 #define RPTR_RPTR_HDR
00024 
00025 #include "debug.h"
00026 
00052 namespace rptr {
00053 
00055   struct Rptr_ReferenceCounter {
00056     inline void Attach() { 
00057       ++counter; 
00058     }
00059     template<class T>
00060     inline void Detach(T *p) { 
00061       if(--counter==0) { 
00062         if(owner) {
00063           delete p; 
00064         }
00065         delete this;
00066       } 
00067     }
00068     inline Rptr_ReferenceCounter(bool owner0):
00069       owner(owner0), counter(0) {}
00070 
00071     bool owner;
00072   private:
00073     unsigned counter;
00074   };
00075 
00077 
00101   template<class T>
00102   class Rptr {
00104     Rptr_ReferenceCounter *refcounter;
00106     T *data;
00107 
00108     template<class TT>
00109     inline static void Dummy(TT * const &) {}
00110 
00111   public:
00112     template<class TT> friend class Rptr;
00114 
00115 
00116     inline Rptr():
00117       refcounter(0),
00118       data(0)
00119     {
00120     }
00122     inline Rptr(const Rptr &src): 
00123       refcounter(src.refcounter),
00124       data(src.data)
00125     { 
00126       if(refcounter) {
00127         refcounter->Attach(); 
00128       }
00129     }
00136     inline Rptr(T *data0, bool owner0=true):
00137       refcounter(0),
00138       data(data0)
00139     { 
00140       if(data) {
00141         refcounter = new Rptr_ReferenceCounter(owner0);
00142         refcounter->Attach(); 
00143       }
00144     }
00147     inline Rptr & Set(T *src, bool owner0=true) 
00148     {
00149       if(refcounter) {
00150         refcounter->Detach(data);
00151       }
00152       refcounter = 0;
00153       data = src;
00154       if(data) {
00155         refcounter = new Rptr_ReferenceCounter(owner0);
00156         refcounter->Attach();
00157       }
00158       return *this;
00159     }
00161     inline ~Rptr() 
00162     {
00163       if(refcounter) {
00164         refcounter->Detach(data); 
00165       }
00166     }
00168 
00169 
00170 
00171     inline T & operator *() const { 
00172       RPTR_DEBUG_CHECK_NULL(data);
00173       return *data; 
00174     }
00176     inline T * operator ->() const { 
00177       RPTR_DEBUG_CHECK_NULL(data);
00178       return data; 
00179     }
00181     template<class TT>
00182     inline operator const Rptr<TT> & () const { 
00183       Dummy<TT>(data); /* Check that corresponding built-in pointer conversion
00184                         * is allowed */
00185       return reinterpret_cast<const Rptr<TT> &>(*this);
00186     }
00188     inline T * Ptr() const { 
00189       return data; 
00190     }
00193     inline bool IsOwner() const { 
00194       return refcounter && refcounter->owner;
00195     }
00198     inline T * Drop() const { 
00199       if(refcounter) {
00200         refcounter->owner = false;
00201       }
00202       return data;
00203     }
00205     inline bool operator ==(const Rptr &rhs) const { 
00206       return data == rhs.data; 
00207     }
00209     inline bool operator ==(const T *rhs) const { 
00210       return data == rhs;
00211     }
00213     inline bool operator !=(const Rptr &rhs) const { 
00214       return data != rhs.data;
00215     }
00217     inline bool operator !=(const T *rhs) const { 
00218       return data != rhs; 
00219     }
00221 
00222 
00223 
00224     inline Rptr & operator =(const Rptr &src) {
00225       Rptr_ReferenceCounter *tmp = refcounter; // Self-assignment is safe!
00226       T *tmpdata = data;
00227       data=src.data;
00228       refcounter=src.refcounter;
00229       if(refcounter) {
00230         refcounter->Attach();
00231       }
00232       if(tmp) {
00233         tmp->Detach(tmpdata);
00234       }
00235       return *this;
00236     }
00237 
00239     inline Rptr & operator =(T *src) { 
00240       return Set(src,true); 
00241     }
00242 
00244     template<class TT>
00245     inline Rptr & DynamicCast(const Rptr<TT> &src) {
00246       Rptr_ReferenceCounter *tmp=refcounter;
00247       T *tmpdata = data;
00248       refcounter = 0;
00249       data=dynamic_cast<T *>(src.data);
00250       if(data) {
00251         refcounter = src.refcounter;
00252         refcounter->Attach();
00253       }
00254       if(tmp) {
00255         tmp->Detach(tmpdata);
00256       }
00257       return *this;
00258     }
00260     template<class TT>
00261     inline Rptr & StaticCast(const Rptr<TT> &src) {
00262       Rptr_ReferenceCounter *tmp=refcounter;
00263       T *tmpdata = data;
00264       refcounter = 0;
00265       data=static_cast<T *>(src.data);
00266       if(data) {
00267         refcounter = src.refcounter;
00268         refcounter->Attach();
00269       }
00270       if(tmp) {
00271         tmp->Detach(tmpdata);
00272       }
00273       return *this;
00274     }
00276   };
00277 
00278 }
00279 #endif

Generated on Wed May 12 15:35:34 2004 for rptr by doxygen 1.3.3