00001 /** @file 00002 00003 A brief file description 00004 00005 @section license License 00006 00007 Licensed to the Apache Software Foundation (ASF) under one 00008 or more contributor license agreements. See the NOTICE file 00009 distributed with this work for additional information 00010 regarding copyright ownership. The ASF licenses this file 00011 to you under the Apache License, Version 2.0 (the 00012 "License"); you may not use this file except in compliance 00013 with the License. You may obtain a copy of the License at 00014 00015 http://www.apache.org/licenses/LICENSE-2.0 00016 00017 Unless required by applicable law or agreed to in writing, software 00018 distributed under the License is distributed on an "AS IS" BASIS, 00019 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00020 See the License for the specific language governing permissions and 00021 limitations under the License. 00022 */ 00023 00024 /*************************** -*- Mod: C++ -*- ****************************** 00025 00026 Atmic and non-atomic smart pointers. 00027 00028 Note: it would have been nice to have one 'Ptr' class, but the 00029 templating system on some compilers is so broken that it cannot 00030 correctly compile Ptr without downcasting the m_ptr object to 00031 a RefCountObj. 00032 00033 00034 ****************************************************************************/ 00035 #if !defined (_Ptr_h_) 00036 #define _Ptr_h_ 00037 00038 #include "ink_atomic.h" 00039 00040 //////////////////////////////////////////////////////////////////////// 00041 // 00042 // class NonAtomicRefCountObj 00043 // prototypical class for reference counting 00044 // 00045 //////////////////////////////////////////////////////////////////////// 00046 class NonAtomicRefCountObj 00047 { 00048 public: 00049 NonAtomicRefCountObj():m_refcount(0) 00050 { 00051 return; 00052 } 00053 NonAtomicRefCountObj(const NonAtomicRefCountObj & s):m_refcount(0) 00054 { 00055 (void) s; 00056 return; 00057 } 00058 virtual ~ NonAtomicRefCountObj() { 00059 return; 00060 } 00061 NonAtomicRefCountObj & operator =(const NonAtomicRefCountObj & s) { 00062 (void) s; 00063 return (*this); 00064 } 00065 00066 int refcount_inc(); 00067 int refcount_dec(); 00068 int refcount() const; 00069 00070 virtual void free() 00071 { 00072 delete this; 00073 } 00074 00075 volatile int m_refcount; 00076 }; 00077 00078 inline int 00079 NonAtomicRefCountObj::refcount_inc() 00080 { 00081 return ++m_refcount; 00082 } 00083 00084 #define NONATOMIC_REF_COUNT_OBJ_REFCOUNT_INC(_x) (_x)->refcount_inc() 00085 00086 inline int 00087 NonAtomicRefCountObj::refcount_dec() 00088 { 00089 return --m_refcount; 00090 } 00091 00092 #define NONATOMIC_REF_COUNT_OBJ_REFCOUNT_DEC(_x) (_x)->refcount_dec() 00093 00094 inline int 00095 NonAtomicRefCountObj::refcount() const 00096 { 00097 return m_refcount; 00098 } 00099 00100 00101 00102 //////////////////////////////////////////////////////////////////////// 00103 // 00104 // class NonAtomicPtr 00105 // 00106 //////////////////////////////////////////////////////////////////////// 00107 template<class T> class NonAtomicPtr { 00108 public: 00109 explicit NonAtomicPtr(T * ptr = 0); 00110 NonAtomicPtr(const NonAtomicPtr<T> &); 00111 ~NonAtomicPtr(); 00112 00113 NonAtomicPtr<T> &operator =(const NonAtomicPtr<T> &); 00114 NonAtomicPtr<T> &operator =(T *); 00115 00116 void clear(); 00117 00118 operator T *() const 00119 { 00120 return (m_ptr); 00121 } 00122 T *operator ->() const 00123 { 00124 return (m_ptr); 00125 } 00126 T & operator *() const 00127 { 00128 return (*m_ptr); 00129 } 00130 00131 int operator ==(const T * p) 00132 { 00133 return (m_ptr == p); 00134 } 00135 int operator ==(const NonAtomicPtr<T> &p) 00136 { 00137 return (m_ptr == p.m_ptr); 00138 } 00139 int operator !=(const T * p) 00140 { 00141 return (m_ptr != p); 00142 } 00143 int operator !=(const NonAtomicPtr<T> &p) 00144 { 00145 return (m_ptr != p.m_ptr); 00146 } 00147 00148 NonAtomicRefCountObj *_ptr() 00149 { 00150 return (NonAtomicRefCountObj *) m_ptr; 00151 } 00152 00153 T *m_ptr; 00154 }; 00155 00156 template <typename T> 00157 NonAtomicPtr<T> make_nonatomic_ptr(T * p) { 00158 return NonAtomicPtr<T>(p); 00159 } 00160 00161 //////////////////////////////////////////////////////////////////////// 00162 // 00163 // inline functions definitions 00164 // 00165 //////////////////////////////////////////////////////////////////////// 00166 template<class T> inline NonAtomicPtr<T>::NonAtomicPtr(T * ptr /* = 0 */ ) 00167 : 00168 m_ptr(ptr) 00169 { 00170 if (m_ptr) 00171 _ptr()->refcount_inc(); 00172 return; 00173 } 00174 00175 template<class T> inline NonAtomicPtr<T>::NonAtomicPtr(const NonAtomicPtr<T> &src) 00176 : 00177 m_ptr(src.m_ptr) 00178 { 00179 if (m_ptr) 00180 _ptr()->refcount_inc(); 00181 return; 00182 } 00183 00184 template<class T> inline NonAtomicPtr<T>::~NonAtomicPtr() 00185 { 00186 if ((m_ptr) && _ptr()->refcount_dec() == 0) { 00187 _ptr()->free(); 00188 } 00189 return; 00190 } 00191 00192 template<class T> inline NonAtomicPtr<T> &NonAtomicPtr<T>::operator =(T * p) 00193 { 00194 T *temp_ptr = m_ptr; 00195 00196 if (m_ptr == p) 00197 return (*this); 00198 00199 m_ptr = p; 00200 00201 if (m_ptr != 0) { 00202 _ptr()->refcount_inc(); 00203 } 00204 00205 if ((temp_ptr) && ((NonAtomicRefCountObj *) temp_ptr)->refcount_dec() == 0) { 00206 ((NonAtomicRefCountObj *) temp_ptr)->free(); 00207 } 00208 00209 return (*this); 00210 } 00211 template<class T> inline void NonAtomicPtr<T>::clear() 00212 { 00213 if (m_ptr) { 00214 if (!((NonAtomicRefCountObj *) m_ptr)->refcount_dec()) 00215 ((NonAtomicRefCountObj *) m_ptr)->free(); 00216 m_ptr = NULL; 00217 } 00218 } 00219 template<class T> inline NonAtomicPtr<T> &NonAtomicPtr<T>::operator =(const NonAtomicPtr<T> &src) 00220 { 00221 return (operator =(src.m_ptr)); 00222 } 00223 00224 00225 //////////////////////////////////////////////////////////////////// 00226 //////////////////////////////////////////////////////////////////// 00227 ////// ATOMIC VERSIONS 00228 //////////////////////////////////////////////////////////////////// 00229 //////////////////////////////////////////////////////////////////// 00230 00231 struct ForceVFPTToTop 00232 { 00233 virtual ~ ForceVFPTToTop() 00234 { 00235 } 00236 }; 00237 00238 00239 //////////////////////////////////////////////////////////////////////// 00240 // 00241 // class RefCountObj 00242 // prototypical class for reference counting 00243 // 00244 //////////////////////////////////////////////////////////////////////// 00245 class RefCountObj: public ForceVFPTToTop 00246 { 00247 public: 00248 RefCountObj():m_refcount(0) 00249 { 00250 } 00251 RefCountObj(const RefCountObj & s):m_refcount(0) 00252 { 00253 (void) s; 00254 return; 00255 } 00256 virtual ~ RefCountObj() { 00257 } 00258 RefCountObj & operator =(const RefCountObj & s) { 00259 (void) s; 00260 return (*this); 00261 } 00262 00263 int refcount_inc(); 00264 int refcount_dec(); 00265 int refcount() const; 00266 00267 virtual void free() 00268 { 00269 delete this; 00270 } 00271 00272 volatile int m_refcount; 00273 }; 00274 00275 // Increment the reference count, returning the new count. 00276 inline int 00277 RefCountObj::refcount_inc() 00278 { 00279 return ink_atomic_increment((int *) &m_refcount, 1) + 1; 00280 } 00281 00282 #define REF_COUNT_OBJ_REFCOUNT_INC(_x) (_x)->refcount_inc() 00283 00284 // Decrement the reference count, returning the new count. 00285 inline int 00286 RefCountObj::refcount_dec() 00287 { 00288 return ink_atomic_increment((int *) &m_refcount, -1) - 1; 00289 } 00290 00291 #define REF_COUNT_OBJ_REFCOUNT_DEC(_x) (_x)->refcount_dec() 00292 00293 inline int 00294 RefCountObj::refcount() const 00295 { 00296 return m_refcount; 00297 } 00298 00299 00300 //////////////////////////////////////////////////////////////////////// 00301 // 00302 // class Ptr 00303 // 00304 //////////////////////////////////////////////////////////////////////// 00305 template<class T> class Ptr { 00306 public: 00307 explicit Ptr(T * p = 0); 00308 Ptr(const Ptr<T> &); 00309 ~Ptr(); 00310 00311 void clear(); 00312 Ptr<T> &operator =(const Ptr<T> &); 00313 Ptr<T> &operator =(T *); 00314 00315 T * to_ptr() { 00316 if (m_ptr && m_ptr->m_refcount == 1) { 00317 T * ptr = m_ptr; 00318 m_ptr = 0; 00319 ptr->m_refcount = 0; 00320 return ptr; 00321 } 00322 return 0; 00323 } 00324 operator T *() const 00325 { 00326 return (m_ptr); 00327 } 00328 T *operator ->() const 00329 { 00330 return (m_ptr); 00331 } 00332 T & operator *() const 00333 { 00334 return (*m_ptr); 00335 } 00336 00337 int operator ==(const T * p) 00338 { 00339 return (m_ptr == p); 00340 } 00341 int operator ==(const Ptr<T> &p) 00342 { 00343 return (m_ptr == p.m_ptr); 00344 } 00345 int operator !=(const T * p) 00346 { 00347 return (m_ptr != p); 00348 } 00349 int operator !=(const Ptr<T> &p) 00350 { 00351 return (m_ptr != p.m_ptr); 00352 } 00353 00354 RefCountObj *_ptr() 00355 { 00356 return (RefCountObj *) m_ptr; 00357 } 00358 00359 T *m_ptr; 00360 }; 00361 00362 template <typename T> 00363 Ptr<T> make_ptr(T * p) { 00364 return Ptr<T>(p); 00365 } 00366 00367 //////////////////////////////////////////////////////////////////////// 00368 // 00369 // inline functions definitions 00370 // 00371 //////////////////////////////////////////////////////////////////////// 00372 template<class T> inline Ptr<T>::Ptr(T * ptr /* = 0 */ ) 00373 : 00374 m_ptr(ptr) 00375 { 00376 if (m_ptr) 00377 _ptr()->refcount_inc(); 00378 return; 00379 } 00380 00381 template<class T> inline Ptr<T>::Ptr(const Ptr<T> &src) 00382 : 00383 m_ptr(src.m_ptr) 00384 { 00385 if (m_ptr) 00386 _ptr()->refcount_inc(); 00387 return; 00388 } 00389 00390 template<class T> inline Ptr<T>::~Ptr() 00391 { 00392 if ((m_ptr) && _ptr()->refcount_dec() == 0) { 00393 _ptr()->free(); 00394 } 00395 return; 00396 } 00397 00398 template<class T> inline Ptr<T> &Ptr<T>::operator =(T * p) 00399 { 00400 T *temp_ptr = m_ptr; 00401 00402 if (m_ptr == p) 00403 return (*this); 00404 00405 m_ptr = p; 00406 00407 if (m_ptr != 0) { 00408 _ptr()->refcount_inc(); 00409 } 00410 00411 if ((temp_ptr) && ((RefCountObj *) temp_ptr)->refcount_dec() == 0) { 00412 ((RefCountObj *) temp_ptr)->free(); 00413 } 00414 00415 return (*this); 00416 } 00417 template<class T> inline void Ptr<T>::clear() 00418 { 00419 if (m_ptr) { 00420 if (!((RefCountObj *) m_ptr)->refcount_dec()) 00421 ((RefCountObj *) m_ptr)->free(); 00422 m_ptr = NULL; 00423 } 00424 } 00425 template<class T> inline Ptr<T> &Ptr<T>::operator =(const Ptr<T> &src) 00426 { 00427 return (operator =(src.m_ptr)); 00428 } 00429 00430 #endif