Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/simpleref.impl

Go to the documentation of this file.
00001 /* **-*-c++-*-**************************************************************
00002   Copyright (C)2002 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: simpleref.impl 1029 2004-02-11 20:45:54Z jungd $
00019   $Revision: 1.3 $
00020   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #ifndef _BASE_REF_
00026 #define _BASE_REF_
00027 
00028 
00029 #include <functional>           // for std::less
00030 #include <typeinfo>             // for std::bad_cast
00031 #include <stdexcept>            // for std::runtime_error
00032 
00033 namespace base
00034 {
00035   
00036   namespace detail
00037   {
00038     struct static_cast_tag {};
00039     struct dynamic_cast_tag {};
00040   }
00041   
00042 /// intrusive reference counted smart pointer.  referenced object must
00043 ///  implement reference() and unreference() (e.g. class Referenced)
00044 template<typename T>
00045 class ref 
00046 {
00047 public:
00048   typedef T element_type;
00049   typedef T* pointer;
00050   typedef T& reference;
00051 
00052   ref() 
00053     : p(pointer(0)) 
00054   {}
00055 
00056   
00057   explicit ref(pointer p) 
00058     : p(p)
00059   {
00060     if (p) p->reference(); 
00061   }
00062   
00063   
00064   ref(const ref& r)
00065     : p(r.p)
00066   {
00067     if (p) p->reference();
00068   }
00069   
00070   template<typename T2>
00071   ref(const ref<T2>& r)
00072    : p(r.get())
00073   {
00074     if (p) p->reference();
00075   }
00076   
00077   
00078   template<typename T2>
00079   ref(const ref<T2>& r, detail::static_cast_tag)
00080   {
00081     p = static_cast<pointer>(r.get());
00082     if (p) p->reference();
00083   }
00084   
00085   template<typename T2>
00086   ref(const ref<T2>& r, detail::dynamic_cast_tag)
00087   {
00088     p = dynamic_cast<pointer>(r.get());
00089     if (r.get() && (!p)) throw std::bad_cast();
00090     if (p) p->reference();
00091   }
00092   
00093   
00094   
00095   ~ref()
00096   {
00097     if (p) 
00098       if (p->unreference())
00099         delete p;
00100   }
00101   
00102   ref& operator=(const ref& r) 
00103   { 
00104     if (&r != this) {
00105       if (p) 
00106         if (p->unreference())
00107           delete p;
00108       p=r.p; 
00109       if (p) p->reference();
00110     }
00111     return *this; 
00112   }
00113   
00114   template<typename T2>
00115   ref& operator=(const ref<T2>& r) 
00116   { 
00117     if (r.get() != this->get()) {
00118       if (p) 
00119         if (p->unreference())
00120           delete p;
00121       p=r.get(); 
00122       if (p) p->reference();
00123     }
00124     return *this; 
00125   }
00126   
00127   pointer get() const { return p; }
00128   
00129   void reset(pointer p = pointer(0))
00130   {
00131     if (p == this->p) {
00132 #ifdef DEBUG
00133       std::cerr << "can't reset to same pointer\n"; abort();
00134 #else
00135       throw std::runtime_error("can't reset to same pointer");
00136 #endif
00137     }
00138     if (this->p) 
00139       if (this->p->unreference())
00140         delete this->p;
00141     this->p = p;
00142   }
00143    
00144    
00145   pointer release()
00146   {
00147     pointer rp = p;
00148     if (p) 
00149       if (p->unreference())
00150         delete p;
00151     p = pointer(0);
00152     return rp;
00153   }
00154    
00155   void swap(ref& r) { std::swap(r.p, p); }
00156    
00157   
00158   bool operator==(const ref& r) const { return p == r.p; }
00159   bool operator!=(const ref& r) const { return p != r.p; }
00160   
00161   template<typename T2>
00162   bool operator==(const ref<T2>& r) const { return p == r.get(); }
00163   
00164   template<typename T2>
00165   bool operator!=(const ref<T2>& r) const { return p != r.get(); }
00166   
00167   template<typename T2>
00168   bool operator==(const T2* p2) const { return p == p2; }
00169   
00170   template<typename T2>
00171   bool operator!=(const T2* p2) const { return p != p2; }
00172   
00173   
00174   reference operator*() 
00175   {
00176     if (!p) {
00177 #ifdef DEBUG
00178       std::cerr << "null pointer\n"; abort();
00179 #else
00180       throw std::runtime_error("null pointer");
00181 #endif
00182     }
00183     return *p; 
00184   }
00185   
00186   reference operator*() const
00187   {
00188     if (!p) {
00189 #ifdef DEBUG
00190       std::cerr << "null pointer\n"; abort();
00191 #else
00192       throw std::runtime_error("null pointer");
00193 #endif
00194     }
00195     return *p; 
00196   }
00197   
00198   pointer operator->() 
00199   { 
00200     if (!p) {
00201 #ifdef DEBUG
00202       std::cerr << "null pointer\n"; abort();
00203 #else
00204       throw std::runtime_error("null pointer");
00205 #endif
00206     }
00207     return p; 
00208   }
00209 
00210   pointer operator->() const
00211   { 
00212     if (!p) {
00213 #ifdef DEBUG
00214       std::cerr << "null pointer\n"; abort();
00215 #else
00216       throw std::runtime_error("null pointer");
00217 #endif
00218     }
00219     return p; 
00220   }
00221   
00222   bool operator!() const { return p == 0; }
00223                                                                                                                                                                                                                                             
00224 private:
00225     // Helper for enabling 'if (sp)'
00226     struct Tester
00227     {
00228         Tester() {}
00229     private:
00230         void operator delete(void*);
00231     };
00232     
00233 public:
00234     // enable 'if (sp)'
00235     operator Tester*() const
00236     {
00237         if (!*this) return 0;
00238         static Tester t;
00239         return &t;
00240     }
00241   
00242 protected:
00243   pointer p;
00244 };
00245 
00246 
00247 template<typename T>
00248 inline void Release(ref<T>& r) { r.release(); }
00249 
00250 template<typename T>
00251 inline typename ref<T>::pointer GetImplRef(ref<T>& r) { return r.get(); }
00252 
00253 template<typename T>
00254 inline void Reset(ref<T>& r, const typename ref<T>::pointer p) { r.reset(p); }
00255 
00256 
00257 template<class T, class U> inline bool operator==(const ref<T>& a, const ref<U>& b)
00258 {
00259     return a.get() == b.get();
00260 }
00261 
00262 template<class T, class U> inline bool operator==(const T* a, const ref<U>& b)
00263 {
00264     return a == b.get();
00265 }
00266 
00267 template<class T, class U> inline bool operator==(const ref<T>& a, const U* b)
00268 {
00269     return a.get() == b;
00270 }
00271                                                                                                                                                                                                                                            
00272 template<class T, class U> inline bool operator!=(const ref<T>& a, const ref<U>& b)
00273 {
00274     return a.get() != b.get();
00275 }
00276 
00277 template<class T, class U> inline bool operator!=(const T* a, const ref<U>& b)
00278 {
00279     return a != b.get();
00280 }
00281 
00282 template<class T, class U> inline bool operator!=(const ref<T>& a, const U* b)
00283 {
00284     return a.get() != b;
00285 }
00286 
00287 
00288 
00289 template<class T, class U> inline bool operator<(const ref<T>& a, const ref<U>& b)
00290 {
00291     return a.get() < b.get();
00292 }
00293 
00294 template<class T, class U> inline bool operator<(const T* a, const ref<U>& b)
00295 {
00296     return a < b.get();
00297 }
00298 
00299 template<class T, class U> inline bool operator<(const ref<T>& a, const U* b)
00300 {
00301     return a.get() < b;
00302 }
00303 
00304 
00305 template<class T, class U> inline bool operator>(const ref<T>& a, const ref<U>& b)
00306 {
00307     return a.get() > b.get();
00308 }
00309 
00310 template<class T, class U> inline bool operator>(const T* a, const ref<U>& b)
00311 {
00312     return a > b.get();
00313 }
00314 
00315 template<class T, class U> inline bool operator>(const ref<T>& a, const U* b)
00316 {
00317     return a.get() > b;
00318 }
00319 
00320 
00321 
00322 template<class T, class U> inline bool operator<=(const ref<T>& a, const ref<U>& b)
00323 {
00324     return a.get() <= b.get();
00325 }
00326 
00327 template<class T, class U> inline bool operator<=(const T* a, const ref<U>& b)
00328 {
00329     return a <= b.get();
00330 }
00331 
00332 template<class T, class U> inline bool operator<=(const ref<T>& a, const U* b)
00333 {
00334     return a.get() <= b;
00335 }
00336 
00337 
00338 template<class T, class U> inline bool operator>=(const ref<T>& a, const ref<U>& b)
00339 {
00340     return a.get() >= b.get();
00341 }
00342 
00343 template<class T, class U> inline bool operator>=(const T* a, const ref<U>& b)
00344 {
00345     return a >= b.get();
00346 }
00347 
00348 template<class T, class U> inline bool operator>=(const ref<T>& a, const U* b)
00349 {
00350     return a.get() >= b;
00351 }
00352 
00353 
00354 
00355 
00356 
00357 
00358 template<class T, class U> ref<T> static_cast_ref(const ref<U>& r)
00359 {
00360     return ref<T>(r, detail::static_cast_tag());
00361 }
00362 
00363 template<class T, class U> ref<T> narrow_cast_ref(const ref<U>& r)
00364 {
00365     return ref<T>(r, detail::dynamic_cast_tag());
00366 }
00367  
00368 template<class T, class U> ref<T> dynamic_cast_ref(const ref<U>& r)
00369 {
00370     return ref<T>(r, detail::dynamic_cast_tag());
00371 }
00372 
00373 #define narrow_ref narrow_cast_ref
00374   
00375   
00376 } // base
00377 
00378 
00379 
00380 // specialization of std::less for ref
00381 namespace std
00382 {
00383   
00384   template<typename T>
00385   struct less< base::ref<T> >
00386     : public binary_function<base::ref<T>, base::ref<T>, bool>
00387   {
00388     bool operator()(const base::ref<T>& lhs, const base::ref<T>& rhs) const
00389     { return less<T*>()(lhs.get(), rhs.get()); }
00390   };
00391   
00392 }
00393 
00394 
00395 #endif
00396 

Generated on Thu Jul 29 15:56:14 2004 for OpenSim by doxygen 1.3.6