Main MRPT website > C++ reference
MRPT logo

smart_ptr.tpp

Go to the documentation of this file.
00001 /*
00002     The STL+ C++ Library Collection
00003 
00004     Website <http://stlplus.sourceforge.net/> Collection <index.html>
00005 
00006 
00007       License Agreement
00008 
00009     <http://www.opensource.org/>
00010 
00011         * License for using the STLplus Library Collection <#license>
00012         * The Intent of this License <#intent>
00013         * How to Comply with this License <#compliance>
00014         * Historical Note <#history>
00015 
00016 
00017         License for using the STLplus Library Collection
00018 
00019     *© 1999-2008 Andy Rushton. All rights reserved.*
00020 
00021     Redistribution and use in source and binary forms, with or without
00022     modification, are permitted provided that the following conditions are met:
00023 
00024         * Redistributions of source code must retain the above Copyright
00025           notice, this list of conditions and the following disclaimer.
00026         * Redistributions in binary form must reproduce the above Copyright
00027           notice, this list of conditions and the following disclaimer in
00028           the documentation and/or other materials provided with the
00029           distribution.
00030         * Neither the name of the STLplus library nor the names of its
00031           contributors may be used to endorse or promote products derived
00032           from this software without specific prior written permission.
00033 
00034     This software is provided by the Copyright holders and contributors "as
00035     is" and any express or implied warranties, including, but not limited
00036     to, the implied warranties of merchantability and fitness for a
00037     particular purpose are disclaimed. In no event shall the Copyright owner
00038     or contributors be liable for any direct, indirect, incidental, special,
00039     exemplary, or consequential damages (including, but not limited to,
00040     procurement of substitute goods or services; loss of use, data, or
00041     profits; or business interruption) however caused and on any theory of
00042     liability, whether in contract, strict liability, or tort (including
00043     negligence or otherwise) arising in any way out of the use of this
00044     software, even if advised of the possibility of such damage.
00045 */
00046 
00047 /*
00048     Modified version of STL+ sources shipped with the Mobile Robot 
00049         Programming Toolkit (MRPT).
00050         
00051         Sources have been modified to support thred-safe smart pointers
00052         through atomic operations.
00053         
00054         2009, Jose Luis Blanco. University of Malaga. 
00055 */
00056 
00057 #ifndef MRPT_SMARTPTR_H
00058 #define MRPT_SMARTPTR_H
00059 
00060 ////////////////////////////////////////////////////////////////////////////////
00061 
00062 //   Author:    Andy Rushton
00063 //   Copyright: (c) Andy Rushton, 2007
00064 //   License:   BSD License, see ../docs/license.html
00065 
00066 ////////////////////////////////////////////////////////////////////////////////
00067 
00068 namespace stlplus
00069 {
00070 
00071   ////////////////////////////////////////////////////////////////////////////////
00072   // internal holder data structure
00073   ////////////////////////////////////////////////////////////////////////////////
00074 
00075   template<typename T,typename COUNTER>
00076   class smart_ptr_holder
00077   {
00078   private:
00079         COUNTER m_count;  //JL: It was...  unsigned m_count;
00080     T* m_data;
00081 
00082     // make these private to disallow copying because the holder doesn't know how to copy
00083     inline smart_ptr_holder(const smart_ptr_holder& s) :
00084       m_count(0), m_data(0)
00085       {
00086       }
00087 
00088     inline smart_ptr_holder& operator=(const smart_ptr_holder& s)
00089       {
00090         return *this;
00091       }
00092 
00093   public:
00094     inline smart_ptr_holder(T* p = 0) : 
00095       m_count(1), m_data(p)
00096       {
00097       }
00098 
00099     ~smart_ptr_holder(void)
00100       {
00101         clear();
00102       }
00103 
00104     inline unsigned long count(void) const
00105       {
00106         return m_count;
00107       }
00108 
00109     inline void increment(void)
00110       {
00111         ++m_count;
00112       }
00113 
00114     inline bool decrement(void)
00115       {
00116         return (--m_count)==0;
00117       }
00118 
00119     inline bool null(void)
00120       {
00121         return m_data == 0;
00122       }
00123 
00124     inline void clear(void)
00125       {
00126         if(m_data)
00127           delete m_data;
00128         m_data = 0;
00129       }
00130 
00131     inline void set(T* p = 0)
00132       {
00133         clear();
00134         m_data = p;
00135       }
00136 
00137     inline T*& pointer(void)
00138       {
00139         return m_data;
00140       }
00141 
00142     inline const T* pointer(void) const
00143       {
00144         return m_data;
00145       }
00146 
00147     inline T& value(void)
00148       {
00149         return *m_data;
00150       }
00151 
00152     inline const T& value(void) const
00153       {
00154         return *m_data;
00155       }
00156   };
00157 
00158   ////////////////////////////////////////////////////////////////////////////////
00159   // smart_ptr_base class
00160   ////////////////////////////////////////////////////////////////////////////////
00161 
00162   ////////////////////////////////////////////////////////////////////////////////
00163   // constructors, assignments and destructors
00164 
00165   // create a null pointer
00166   template <typename T, typename C, typename COUNTER>
00167   smart_ptr_base<T,C,COUNTER>::smart_ptr_base(void) :
00168     m_holder(new smart_ptr_holder<T,COUNTER>)
00169   {
00170   }
00171 
00172   // create a pointer containing a *copy* of the object pointer
00173   template <typename T, typename C, typename COUNTER>
00174   smart_ptr_base<T,C,COUNTER>::smart_ptr_base(const T& data) throw(illegal_copy) :
00175     m_holder(new smart_ptr_holder<T,COUNTER>)
00176   {
00177     m_holder->set(C()(data));
00178   }
00179 
00180   // create a pointer containing a dynamically created object
00181   // Note: the object must be allocated *by the user* with new
00182   // constructor form - must be called in the form smart_ptr<type> x(new type(args))
00183   template <typename T, typename C, typename COUNTER>
00184   smart_ptr_base<T,C,COUNTER>::smart_ptr_base(T* data) :
00185     m_holder(new smart_ptr_holder<T,COUNTER>)
00186   {
00187     m_holder->set(data);
00188   }
00189 
00190   // copy constructor implements counted referencing - no copy is made
00191   template <typename T, typename C, typename COUNTER>
00192   smart_ptr_base<T,C,COUNTER>::smart_ptr_base(const smart_ptr_base<T,C,COUNTER>& r) :
00193     m_holder(0)
00194   {
00195     m_holder = r.m_holder;
00196     m_holder->increment();
00197   }
00198 
00199   // destructor decrements the reference count and delete only when the last reference is destroyed
00200   template <typename T, typename C, typename COUNTER>
00201   smart_ptr_base<T,C,COUNTER>::~smart_ptr_base(void)
00202   {
00203     if(m_holder->decrement())
00204       delete m_holder;
00205   }
00206 
00207   //////////////////////////////////////////////////////////////////////////////
00208   // logical tests to see if there is anything contained in the pointer since it can be null
00209 
00210   template <typename T, typename C, typename COUNTER>
00211   inline bool smart_ptr_base<T,C,COUNTER>::null(void) const
00212   {
00213     return m_holder->null();
00214   }
00215 
00216   template <typename T, typename C, typename COUNTER>
00217   inline bool smart_ptr_base<T,C,COUNTER>::present(void) const
00218   {
00219     return !m_holder->null();
00220   }
00221 
00222   template <typename T, typename C, typename COUNTER>
00223   bool smart_ptr_base<T,C,COUNTER>::operator!(void) const
00224   {
00225     return m_holder->null();
00226   }
00227 
00228   template <typename T, typename C, typename COUNTER>
00229   smart_ptr_base<T,C,COUNTER>::operator bool(void) const
00230   {
00231     return !m_holder->null();
00232   }
00233 
00234   //////////////////////////////////////////////////////////////////////////////
00235   // dereference operators and functions
00236 
00237   template <typename T, typename C, typename COUNTER>
00238   inline T& smart_ptr_base<T,C,COUNTER>::operator*(void) throw(null_dereference)
00239   {
00240     if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
00241     return m_holder->value();
00242   }
00243 
00244   template <typename T, typename C, typename COUNTER>
00245   inline const T& smart_ptr_base<T,C,COUNTER>::operator*(void) const throw(null_dereference)
00246   {
00247     if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
00248     return m_holder->value();
00249   }
00250 
00251   template <typename T, typename C, typename COUNTER>
00252   inline T* smart_ptr_base<T,C,COUNTER>::operator->(void) throw(null_dereference)
00253   {
00254     if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
00255     return m_holder->pointer();
00256   }
00257 
00258   template <typename T, typename C, typename COUNTER>
00259   inline const T* smart_ptr_base<T,C,COUNTER>::operator->(void) const throw(null_dereference)
00260   {
00261     if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
00262     return m_holder->pointer();
00263   }
00264 
00265   //////////////////////////////////////////////////////////////////////////////
00266   // explicit function forms of the above assignment dereference operators
00267 
00268   template <typename T, typename C, typename COUNTER>
00269   inline void smart_ptr_base<T,C,COUNTER>::set_value(const T& data) throw(illegal_copy)
00270   {
00271     m_holder->set(C()(data));
00272   }
00273 
00274   template <typename T, typename C, typename COUNTER>
00275   inline T& smart_ptr_base<T,C,COUNTER>::value(void) throw(null_dereference)
00276   {
00277     if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
00278     return m_holder->value();
00279   }
00280 
00281   template <typename T, typename C, typename COUNTER>
00282   inline const T& smart_ptr_base<T,C,COUNTER>::value(void) const throw(null_dereference)
00283   {
00284     if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
00285     return m_holder->value();
00286   }
00287 
00288   template <typename T, typename C, typename COUNTER>
00289   void smart_ptr_base<T,C,COUNTER>::set(T* data)
00290   {
00291     m_holder->set(data);
00292   }
00293 
00294   template <typename T, typename C, typename COUNTER>
00295   inline T* smart_ptr_base<T,C,COUNTER>::pointer(void)
00296   {
00297     return m_holder->pointer();
00298   }
00299 
00300   template <typename T, typename C, typename COUNTER>
00301   inline const T* smart_ptr_base<T,C,COUNTER>::pointer(void) const
00302   {
00303     return m_holder->pointer();
00304   }
00305 
00306   ////////////////////////////////////////////////////////////////////////////////
00307   // functions to manage counted referencing
00308 
00309   // make this an alias of the passed object
00310   template <typename T, typename C, typename COUNTER>
00311   void smart_ptr_base<T,C,COUNTER>::alias(const smart_ptr_base<T,C,COUNTER>& r)
00312   {
00313     // make it alias-copy safe - this means that I don't try to do the
00314     // assignment if r is either the same object or an alias of it
00315     //   if (m_holder == r.m_holder) return;
00316     //   if (m_holder->decrement())
00317     //     delete m_holder;
00318     //   m_holder = r.m_holder;
00319     //   m_holder->increment();
00320     make_alias(r.m_holder);
00321   }
00322 
00323   template <typename T, typename C, typename COUNTER>
00324   bool smart_ptr_base<T,C,COUNTER>::aliases(const smart_ptr_base<T,C,COUNTER>& r) const
00325   {
00326     return m_holder == r.m_holder;
00327   }
00328 
00329   template <typename T, typename C, typename COUNTER>
00330   unsigned smart_ptr_base<T,C,COUNTER>::alias_count(void) const
00331   {
00332     return m_holder->count();
00333   }
00334 
00335   template <typename T, typename C, typename COUNTER>
00336   void smart_ptr_base<T,C,COUNTER>::clear(void)
00337   {
00338     m_holder->clear();
00339   }
00340 
00341   template <typename T, typename C, typename COUNTER>
00342   void smart_ptr_base<T,C,COUNTER>::clear_unique(void)
00343   {
00344     if (m_holder->count() == 1)
00345       m_holder->clear();
00346     else
00347     {
00348       m_holder->decrement();
00349       m_holder = 0;
00350       m_holder = new smart_ptr_holder<T,COUNTER>;
00351     }
00352   }
00353 
00354   template <typename T, typename C, typename COUNTER>
00355   void smart_ptr_base<T,C,COUNTER>::make_unique(void) throw(illegal_copy)
00356   {
00357     if (m_holder->count() > 1)
00358     {
00359       smart_ptr_holder<T,COUNTER>* old_holder = m_holder;
00360       m_holder->decrement();
00361       m_holder = 0;
00362       m_holder = new smart_ptr_holder<T,COUNTER>;
00363       if (old_holder->pointer())
00364         m_holder->set(C()(old_holder->value()));
00365     }
00366   }
00367 
00368   template <typename T, typename C, typename COUNTER>
00369   void smart_ptr_base<T,C,COUNTER>::copy(const smart_ptr_base<T,C,COUNTER>& data) throw(illegal_copy)
00370   {
00371     alias(data);
00372     make_unique();
00373   }
00374 
00375   // internal function for distinguishing unique smart_ptr objects
00376   // used for example in persistence routines
00377 
00378   template <typename T, typename C, typename COUNTER>
00379   void* smart_ptr_base<T,C,COUNTER>::handle(void) const
00380   {
00381     return m_holder;
00382   }
00383 
00384   template <typename T, typename C, typename COUNTER>
00385   void smart_ptr_base<T,C,COUNTER>::make_alias(void* handle)
00386   {
00387     smart_ptr_holder<T,COUNTER>* r_holder = (smart_ptr_holder<T,COUNTER>*)handle;
00388     if (m_holder != r_holder)
00389     {
00390       if (m_holder->decrement())
00391         delete m_holder;
00392       m_holder = r_holder;
00393       m_holder->increment();
00394     }
00395   }
00396 
00397   ////////////////////////////////////////////////////////////////////////////////
00398 
00399 } // end namespace stlplus
00400 
00401 #endif
00402 



Page generated by Doxygen 1.7.3 for MRPT 0.9.4 SVN: at Sat Mar 26 06:40:17 UTC 2011