Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

Ref.h

Go to the documentation of this file.
00001 /* SimData: Data Infrastructure for Simulations
00002  * Copyright (C) 2002 Mark Rose <tm2@stm.lbl.gov>
00003  * 
00004  * This file is part of SimData.
00005  * 
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  * 
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019  */
00020 
00021 
00029 #ifndef __SIMDATA_REF_H__
00030 #define __SIMDATA_REF_H__
00031 
00032 #include <cassert>
00033 #include <list>
00034 #include <vector>
00035 
00036 #include <SimData/Namespace.h>
00037 #include <SimData/Export.h>
00038 #include <SimData/Exception.h>
00039 #include <SimData/Log.h>
00040 
00041 
00042 NAMESPACE_SIMDATA
00043 
00044 
00045 class Referenced;
00046 class ReferencePointer;
00047 class LinkBase;
00048 
00049 
00050 SIMDATA_EXCEPTION(ConversionError);
00051 
00052 
00063 template<class T>
00064 class Ref {
00065 public:
00066         typedef std::vector< Ref<T> > vector;
00067         typedef std::list< Ref<T> > list;
00068 
00069         /* TODO add Python bindings
00070         // SWIG python specific comparisons
00071         bool __eq__(const Ref& other);
00072         bool __ne__(const Ref& other); 
00073         */
00074         
00075 
00078         Ref(): _reference(0) {
00079         }
00080 
00081 
00084         Ref(T* ptr): _reference(ptr) {
00085                 if (ptr) ptr->_ref();
00086         }
00087 
00090         Ref(LinkBase const & r): _reference(0) {
00091                 _rebind(r._get());
00092         }
00093 
00096         template <typename Q>
00097         Ref(Ref<Q> const & r): _reference(0) {
00098                 Q *rp = r.get();
00099                 if (rp != 0) {
00100                         //rp->_ref();
00101                         //_reference = static_cast<T*>(rp);
00102                         _rebind(rp);
00103                 }
00104         }
00105 
00108         Ref(Ref const & r): _reference(r._reference) {
00109                 if (_reference != 0) _reference->_ref();
00110         }
00111 
00115         ~Ref() {
00116                 if (_reference) _reference->_deref();
00117         }
00118 
00121         inline bool unique() const {
00122                 if (_reference == 0) return true;
00123                 return (_reference->_count() == 1);
00124         }
00125 
00128         inline int count() const {
00129                 if (_reference == 0) return 1;
00130                 return _reference->_count();
00131         }
00132 
00133 #ifndef SWIG
00134 
00136         template <class Q>
00137         Ref const & operator=(Ref<Q> const & r) {
00138                 _rebind(r.get());
00139                 return *this;
00140         }
00141 
00144         Ref const & operator=(Ref const & r) {
00145                 _rebind(r.get());
00146                 return *this;
00147         }
00148 
00151         LinkBase const & operator=(LinkBase const & r) {
00152                 _rebind(r._get());
00153                 return r;
00154         }
00155 
00158         template <class Q>
00159         inline Q *operator=(Q *ptr) {
00160                 _rebind(ptr);
00161                 return ptr;
00162         }
00163 
00168         inline void *operator=(void *ptr) {
00169                 assert(ptr==0);
00170                 if (_reference != 0) _reference->_deref();
00171                 _reference = 0;
00172                 return ptr;
00173         }
00174 #endif // SWIG
00175 
00176 
00179         inline T* get() const {
00180                 return _reference;
00181         }
00182 
00185         inline T* operator->() const {
00186                 return _reference;
00187         }
00188 
00191         inline T & operator*() const {
00192                 return *_reference;
00193         }
00194 
00195 #ifndef SWIG
00196 
00198         inline bool operator!() const {
00199                 return _reference == 0;
00200         }
00201 #endif // SWIG
00202 
00205         inline bool valid() const {
00206                 return _reference != 0;
00207         }
00208         
00211         template <class Q>
00212         inline bool operator==(Ref<Q> const & p) const {
00213                 return _reference == p.get();
00214         }
00215 
00218         inline bool operator==(Referenced const * p) const {
00219                 return _reference == p;
00220         }
00221 
00224         template <class Q>
00225         inline bool operator!=(Ref<Q> const & p) const {
00226                 return _reference != p.get();
00227         }
00228 
00231         inline bool operator!=(Referenced const * p) const {
00232                 return _reference != p;
00233         }
00234 
00235 
00236 protected:
00239         template <class Q>
00240         void _rebind(Q* ptr) {
00241                 if (ptr) ptr->_ref();
00242                 if (_reference != 0) _reference->_deref();
00243                 _reference = dynamic_cast<T*>(ptr);
00244                 if (_reference == 0 && ptr != 0) {
00245                         SIMDATA_LOG(LOG_ALL, LOG_ERROR, "simdata::Ref() assignment: incompatible types (dynamic cast failed).");
00246                         throw ConversionError();
00247                 }
00248         }
00249 
00252         T* _reference;
00253 };
00254 
00255 
00262 class SIMDATA_EXPORT Referenced {
00263 
00264 template <class T> friend class Ref;
00265 friend class ReferencePointer;
00266 
00267 public:
00268         Referenced(): __count(0) {}
00269 
00270 protected:
00279         virtual ~Referenced() {
00280                 if (__count != 0) {
00281                         SIMDATA_LOG(LOG_ALL, LOG_ERROR, "simdata::Referenced(" << std::hex << int(this) << ") deleted with non-zero reference count (" << __count << "): memory corruption possible.");
00282                 }
00283         }
00284 
00285 private:
00286         inline void _ref() const { ++__count; }
00287 
00288         inline void _deref() const { 
00289                 if (--__count <= 0) {
00290                         delete this;
00291                 }
00292         }
00293         inline unsigned _count() const { return __count; }
00294 
00295         mutable unsigned __count;
00296 
00297         Referenced(Referenced const &); //: __count(0) {}
00298 
00299 #ifndef SWIG
00300         inline Referenced& operator=(Referenced const &);// { return *this; }
00301 #endif // SWIG
00302 
00303 };
00304 
00305 
00306 NAMESPACE_SIMDATA_END
00307 
00308 
00309 #endif //__SIMDATA_OBJECT_H__
00310 

SimData version pre-0.4.0. For more information on SimData, visit the SimData Homepage.

Generated on Tue Oct 14 12:06:39 2003, using Doxygen 1.2.18.

[SF.net]