auto_reference.h
Go to the documentation of this file.00001 // -*-c++-*- 00002 //----------------------------< /-/ CLARAty /-/ >------------------------------ 00003 /** 00004 * @file auto_reference.h 00005 * 00006 * Auto reference similar to auto pointers 00007 * 00008 * <br>@b Designer(s): Randy Sargent 00009 * <br>@b Author(s): Randy Sargent 00010 * <br>@b Date: March 13, 2004 00011 * 00012 * <b>Software License:</b><br> 00013 * <code> http://claraty.jpl.nasa.gov/license/open_src/ or 00014 * file: license/open_src.txt </code> 00015 * 00016 * © 2006, Jet Propulsion Laboratory, California Institute of Technology<br> 00017 * © 2006, NASA Ames Research Center 00018 * 00019 * $Revision: 1.4 $ 00020 */ 00021 //----------------------------------------------------------------------------- 00022 00023 #ifndef AUTO_REF_H 00024 #define AUTO_REF_H 00025 00026 #include "claraty/share.h" 00027 00028 #include <iostream> 00029 #include <assert.h> 00030 00031 // ACE includes 00032 //#include "ace/Synch.h" 00033 #include "claraty/semaphore.h" 00034 00035 namespace claraty { 00036 00037 template <class T> class Auto_Ref; 00038 template <class T> class const_Auto_Ref; 00039 00040 // Clay had to pull this out of the private section of Auto_Ref because of 00041 // compiler confusion resulting from mixing Auto_Ref's of different types. 00042 // So instead of keeping it as a private Auto_Ref helper class, the thing is 00043 // entirely private, but it keeps Auto_Ref as a friend. 00044 template<class RT> 00045 class ref_counter { 00046 int refcount; 00047 //mutable ACE_Recursive_Thread_Mutex lock; 00048 mutable Semaphore lock; 00049 RT *_rep; 00050 00051 explicit ref_counter(const ref_counter&); 00052 00053 friend class Auto_Ref<RT>; 00054 friend class const_Auto_Ref<RT>; 00055 00056 ref_counter(RT *&r) : refcount(1), lock(), _rep(r) { } 00057 ref_counter() : refcount(1), lock(), _rep(NULL) { } 00058 ~ref_counter() { } 00059 00060 void inc() { 00061 lock.acquire(); 00062 refcount++; 00063 lock.release(); 00064 } 00065 00066 int dec() { 00067 lock.acquire(); 00068 if (--refcount == 0) 00069 delete _rep; 00070 int val = refcount; 00071 lock.release(); 00072 return val; 00073 } 00074 00075 // Calling this function probably won't do what you want, since 00076 // the refcount can be invalidated before it is returned 00077 int get_count() const { 00078 lock.acquire(); 00079 int val = refcount; 00080 lock.release(); 00081 return val; 00082 } 00083 00084 void make_null_if_unique() { 00085 lock.acquire(); 00086 if (refcount == 1) { 00087 delete _rep; 00088 _rep= NULL; 00089 } 00090 lock.release(); 00091 } 00092 }; 00093 00094 template <class T> 00095 class Auto_Ref { 00096 friend class const_Auto_Ref<T>; 00097 00098 ref_counter<T> *_rc; 00099 00100 public: 00101 Auto_Ref() { _rc= new ref_counter<T>(); } 00102 explicit Auto_Ref(T *&ptr) { _rc = new ref_counter<T>(ptr); ptr = 0; } 00103 Auto_Ref(const Auto_Ref& rhs) { 00104 _rc = rhs._rc; 00105 _rc->inc(); 00106 } 00107 ~Auto_Ref() { 00108 if (_rc->dec() == 0) delete _rc; 00109 } 00110 00111 // Why does this function have such a long name? To remind you that you 00112 // really shouldn't be calling it, ever. It should only be used by the 00113 // internal operator== function. 00114 const void *get_const_representation_pointer() const { return _rc; } 00115 00116 Auto_Ref& operator=(const Auto_Ref& rhs) { 00117 if (_rc != rhs._rc) { 00118 if (_rc->dec() == 0) delete _rc; 00119 _rc = rhs._rc; 00120 _rc->inc(); 00121 } 00122 return *this; 00123 } 00124 00125 template <class R> 00126 bool operator==(const Auto_Ref<R>& rhs) const { 00127 return static_cast<void*>(_rc) == rhs.get_const_representation_pointer(); 00128 } 00129 00130 template <class R> 00131 bool operator!=(const Auto_Ref<R>& rhs) const { 00132 return !operator==(rhs); 00133 } 00134 00135 // evil casting function, which casts what we're reffing to a subclass 00136 // thereof. This would throw bad cast if the dynamic cast fails, but for now 00137 // it simply causes the program to abort. 00138 template <class S> 00139 void cast_to(Auto_Ref<S>& rhs) { 00140 if (dynamic_cast<S*>(_rc->_rep) == NULL) { 00141 std::cerr << "Illegal attempt to cast an Auto_Ref<T> to an Auto_Ref<U> where " 00142 "U is not castable from T (or from a NULL Auto_Ref)" << std::endl; 00143 S& dummy = dynamic_cast<S&>(*_rc->_rep); // will throw bad_cast 00144 } 00145 ref_counter<S> *rc_subclass = reinterpret_cast<ref_counter<S>*>(_rc); 00146 rhs.reset_rc(rc_subclass); 00147 } 00148 00149 // casting to something of the same type is esy 00150 void cast_to(Auto_Ref<T>& rhs) { 00151 rhs = *this; 00152 } 00153 00154 // This can only be called by other Auto_Ref's since they're the only ones 00155 // who have access to the ref_counter sibling type. The function is public 00156 // because Auto_Ref's of other types are not our friends. 00157 void reset_rc(ref_counter<T> *new_rc) { 00158 if (_rc->dec() == 0) delete _rc; 00159 _rc = new_rc; 00160 _rc->inc(); 00161 } 00162 00163 void reset(T *&ptr) { 00164 if (_rc->dec() == 0) delete _rc; 00165 _rc = new ref_counter<T>(ptr); 00166 ptr = 0; 00167 } 00168 00169 T *get() const { 00170 return _rc->_rep; 00171 } 00172 00173 void get_ptr(T *&p) const { 00174 p = _rc->_rep; 00175 } 00176 00177 template <class U> 00178 void get_ptr(U *&p) { 00179 p = dynamic_cast<U*>(_rc->_rep); 00180 } 00181 00182 // Frees object and changes pointer to NULL if you have 00183 // the only copy 00184 void make_null_if_unique() { 00185 _rc->make_null_if_unique(); 00186 } 00187 00188 void make_unique() { 00189 _rc->lock.acquire(); 00190 if (_rc->get_count() <= 1) { 00191 assert(_rc->get_count() == 1); // should never get to zero while we care 00192 _rc->lock.release(); 00193 } else { 00194 T *copy = _rc->_rep->clone(); 00195 ref_counter<T> *rc = new ref_counter<T>(copy); 00196 _rc->dec(); 00197 assert(_rc->get_count() > 0); // since we know it was greater than 1 00198 _rc->lock.release(); 00199 _rc = rc; 00200 } 00201 } 00202 00203 const T& operator*() const { 00204 return *_rc->_rep; 00205 } 00206 00207 const T *operator->() const { 00208 return _rc->_rep; 00209 } 00210 00211 T& operator*() { 00212 return *_rc->_rep; 00213 } 00214 00215 T *operator->() { 00216 return _rc->_rep; 00217 } 00218 00219 operator bool() const { 00220 return !!_rc->_rep; 00221 } 00222 bool operator!() const { 00223 return !_rc->_rep; 00224 } 00225 }; 00226 00227 template <class T> 00228 class const_Auto_Ref { 00229 ref_counter<T> *_rc; 00230 public: 00231 const_Auto_Ref() { _rc = new ref_counter<T>(); } 00232 const_Auto_Ref(const const_Auto_Ref& rhs) { 00233 _rc = rhs._rc; 00234 _rc->inc(); 00235 } 00236 const_Auto_Ref(const Auto_Ref<T>& rhs) { 00237 _rc = rhs._rc; 00238 _rc->inc(); 00239 } 00240 ~const_Auto_Ref() { 00241 if (_rc->dec() == 0) delete _rc; 00242 } 00243 00244 // Why does this function have such a long name? To remind you that you 00245 // really shouldn't be calling it, ever. It should only be used by the 00246 // internal operator== function. 00247 const void *get_const_representation_pointer() const { return _rc; } 00248 00249 const_Auto_Ref& operator=(const const_Auto_Ref& rhs) { 00250 if (_rc != rhs._rc) { 00251 if (_rc->dec() == 0) delete _rc; 00252 _rc = rhs._rc; 00253 _rc->inc(); 00254 } 00255 return *this; 00256 } 00257 00258 // evil casting function, which casts what we're reffing to a subclass 00259 // thereof. This would throw bad cast if the dynamic cast fails, but for now 00260 // it simply causes the program to abort. 00261 template <class S> 00262 void cast_to(const_Auto_Ref<S>& rhs) { 00263 if (dynamic_cast<S*>(_rc->_rep) == NULL) { 00264 std::cerr << "Illegal attempt to cast an Auto_Ref<T> to an Auto_Ref<U> where " 00265 "U is not castable from T (or from a NULL Auto_Ref)" << std::endl; 00266 S& dummy = dynamic_cast<S&>(*_rc->_rep); // will throw bad_cast 00267 } 00268 ref_counter<S> *rc_subclass = reinterpret_cast<ref_counter<S>*>(_rc); 00269 rhs.reset_rc(rc_subclass); 00270 } 00271 00272 // casting to something of the same type is esy 00273 void cast_to(const_Auto_Ref<T>& rhs) { 00274 rhs = *this; 00275 } 00276 00277 // This can only be called by other Auto_Ref's since they're the only ones 00278 // who have access to the ref_counter sibling type. The function is public 00279 // because Auto_Ref's of other types are not our friends. 00280 void reset_rc(ref_counter<T> *new_rc) { 00281 if (_rc->dec() == 0) delete _rc; 00282 _rc = new_rc; 00283 _rc->inc(); 00284 } 00285 00286 template <class R> 00287 bool operator==(const const_Auto_Ref<R>& rhs) const { 00288 return static_cast<void*>(_rc) == rhs.get_const_representation_pointer(); 00289 } 00290 00291 template <class R> 00292 bool operator!=(const const_Auto_Ref<R>& rhs) const { 00293 return !operator==(rhs); 00294 } 00295 const T& operator*() const { 00296 return *_rc->_rep; 00297 } 00298 00299 const T *operator->() const { 00300 return _rc->_rep; 00301 } 00302 00303 operator bool() const { 00304 return !!_rc->_rep; 00305 } 00306 bool operator!() const { 00307 return !_rc->_rep; 00308 } 00309 }; 00310 00311 } // namespace claraty 00312 00313 #endif // AUTO_REF_H