Main MRPT website > C++ reference
MRPT logo

smart_ptr.hpp

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 
00058 #ifndef STLPLUS_SMART_PTR
00059 #define STLPLUS_SMART_PTR
00060 ////////////////////////////////////////////////////////////////////////////////
00061 
00062 //   Author:    Andy Rushton
00063 //   Copyright: (c) Andy Rushton, 2007
00064 //   License:   BSD License, see ../docs/license.html
00065 
00066 //   A smart pointer is a memory-managing pointer to an object. If you like, it
00067 //   is a zero-dimensional container.
00068 
00069 //   Assignment of smart pointers result in multiple aliases of the same object.
00070 //   The term alias is used to differentiate from conventional pointers because
00071 //   the semantics are different.
00072 
00073 //   Aliases can be turned into copies if the pointed-to class supports copying.
00074 
00075 //   The base class is smart_ptr_base which defines the common interface. Then
00076 //   there are three subclasses which have the same interface but different copy
00077 //   semantics:
00078 
00079 //   - smart_ptr        for simple types and classes which have copy constructors
00080 //   - smart_ptr_clone  for polymorphic class hierarchies which are copied using a clone method
00081 //   - smart_ptr_nocopy for any class that cannot or should not be copied
00082 
00083 ////////////////////////////////////////////////////////////////////////////////
00084 #include "containers_fixes.hpp"
00085 #include "exceptions.hpp"
00086 #include <map>
00087 #include <string>
00088 
00089 #include <mrpt/synch/atomic_incr.h>   // JLB: For atomic_count. See smart_ptr.tpp
00090 
00091 namespace stlplus
00092 {
00093 
00094   ////////////////////////////////////////////////////////////////////////////////
00095   // internals
00096 
00097   template<typename T,typename COUNTER> class smart_ptr_holder;
00098 
00099   ////////////////////////////////////////////////////////////////////////////////
00100   // Base class
00101   ////////////////////////////////////////////////////////////////////////////////
00102 
00103   template<typename T, typename C, typename COUNTER> // Typically: COUNTER = mrpt::synch::CAtomicCounter>
00104   class smart_ptr_base
00105   {
00106   public:
00107     //////////////////////////////////////////////////////////////////////////////
00108     // member type definitions
00109 
00110     typedef T value_type;
00111     typedef T& reference;
00112     typedef const T& const_reference;
00113     typedef C value_copy;
00114 
00115     //////////////////////////////////////////////////////////////////////////////
00116     // constructors and destructors
00117 
00118     // create a null pointer
00119     smart_ptr_base(void);
00120 
00121     // create a pointer containing a *copy* of the object using the template parameter C
00122     // this copy is taken because the pointer class maintains a dynamically allocated object
00123     // and the T& may not be (usually is not) dynamically allocated
00124     explicit smart_ptr_base(const T& data) throw(illegal_copy);
00125 
00126     // create a pointer containing a dynamically created object
00127     // Note: the object must be allocated *by the user* with new
00128     // constructor form - must be called in the form smart_ptr_base<type> x(new type(args))
00129     explicit smart_ptr_base(T* data);
00130 
00131     // copy constructor implements aliasing so no copy is made
00132     explicit smart_ptr_base(const smart_ptr_base<T,C,COUNTER>& r);
00133 
00134     // destructor decrements the reference count and delete only when the last reference is destroyed
00135     ~smart_ptr_base(void);
00136 
00137     //////////////////////////////////////////////////////////////////////////////
00138     // logical tests to see if there is anything contained in the pointer since it can be null
00139 
00140     // there are two forms:explicit and implicit
00141     // implicit: if(!r) or if(r)
00142     // explicit: if(r.null()) or if(r.present())
00143     operator bool(void) const;
00144     bool operator!(void) const;
00145     bool present(void) const;
00146     bool null(void) const;
00147 
00148     //////////////////////////////////////////////////////////////////////////////
00149     // dereference operators and functions
00150 
00151     // dereference the smart pointer to get the object - use in the form *p1
00152     T& operator*(void) throw(null_dereference);
00153     const T& operator*(void) const throw(null_dereference);
00154 
00155     // used as a prefix to a member access to the contained object e.g. p1->print() calls T::print()
00156     T* operator->(void) throw(null_dereference);
00157     const T* operator->(void) const throw(null_dereference);
00158 
00159     //////////////////////////////////////////////////////////////////////////////
00160     // explicit function forms of the above assignment and dereference operators
00161 
00162     // set the value - note that this does a copy using the C template parameter
00163     void set_value(const T& data) throw(illegal_copy);
00164     // get the value
00165     T& value(void) throw(null_dereference);
00166     const T& value(void) const throw(null_dereference);
00167 
00168     // set the pointer
00169     // deletes the previous pointer and adopts the passed pointer instead
00170     // Note: the object must be allocated *by the user* with new
00171     // Warning: it is very easy to break the memory management with this operation
00172     void set(T* data = 0);
00173     // get the pointer
00174     T* pointer(void);
00175     const T* pointer(void) const;
00176 
00177     //////////////////////////////////////////////////////////////////////////////
00178     // functions to manage aliases
00179 
00180     // make this an alias of the passed object
00181     inline void alias(const smart_ptr_base<T,C,COUNTER>&);
00182 
00183     // test whether two pointers point to the same object(known as aliasing the object)
00184     // used in the form if(a.aliases(b))
00185     inline bool aliases(const smart_ptr_base<T,C,COUNTER>&) const;
00186 
00187     // find the number of aliases - used when you need to know whether an
00188     // object is still referred to from elsewhere (rare!)
00189     inline unsigned alias_count(void) const;
00190 
00191     // delete the object and make the pointer null - does not make it unique
00192     // first, so all other pointers to this will be null too
00193     inline void clear(void);
00194 
00195     // make the pointer unique and null in one step - does not affect other
00196     // pointers that were pointing to the same object
00197     inline void clear_unique(void);
00198 
00199     //////////////////////////////////////////////////////////////////////////////
00200     // functions that involve copying
00201 
00202     // these functions use the copy functor passed as the template parameter C
00203     // to copy the object with the right copy semantics. If the copy functor
00204     // is no_copy, an exception will be thrown.
00205 
00206     // make this pointer unique with respect to any other references to the same object
00207     // if this pointer is already unique, it does nothing - otherwise it copies the object
00208     inline void make_unique(void) throw(illegal_copy);
00209 
00210     // make this pointer a unique copy of the parameter
00211     // useful for expressions like p1.copy(p2) which makes p1 a pointer to a unique copy of the contents of p2
00212     void copy(const smart_ptr_base<T,C,COUNTER>&) throw(illegal_copy);
00213 
00214   protected:
00215     smart_ptr_holder<T,COUNTER>* m_holder;
00216 
00217   public:
00218     // internal use only - had to make them public because they need to be
00219     // accessed by routines that could not be made friends
00220     void* handle(void) const;
00221     void make_alias(void* handle);
00222   };
00223 
00224   ////////////////////////////////////////////////////////////////////////////////
00225   // copy functors implementing the three possible copy semantics
00226 
00227   // constructor_copy uses the copy constructor of the object - used for simple types
00228 
00229   template <typename T>
00230   class constructor_copy
00231   {
00232   public:
00233     T* operator() (const T& from) throw()
00234       {
00235         return new T(from);
00236       }
00237   };
00238 
00239   // clone_copy uses the clone method of the object - used for polymorphic types
00240 
00241   template <typename T>
00242   class clone_copy
00243   {
00244   public:
00245     T* operator() (const T& from) throw()
00246       {
00247         return from.clone();
00248       }
00249   };
00250 
00251   // no_copy throws an exception - used for types that cannot be copied
00252 
00253   template <typename T>
00254   class no_copy
00255   {
00256   public:
00257     T* operator() (const T& from) throw(illegal_copy)
00258       {
00259         throw illegal_copy("no_copy functor called");
00260         return 0;
00261       }
00262   };
00263 
00264   ////////////////////////////////////////////////////////////////////////////////
00265   // smart_ptr        for simple types and classes which have copy constructors
00266 
00267   template <typename T,typename COUNTER = mrpt::synch::CAtomicCounter>
00268   class smart_ptr : public smart_ptr_base<T, constructor_copy<T>, COUNTER  >
00269   {
00270   public:
00271     smart_ptr(void) {}
00272     explicit smart_ptr(const T& data) : smart_ptr_base<T, constructor_copy<T>,COUNTER >(data) {}
00273     explicit smart_ptr(T* data) : smart_ptr_base<T, constructor_copy<T>,COUNTER >(data) {}
00274     smart_ptr<T>& operator=(const T& data) {set_value(data); return *this;}
00275     smart_ptr<T>& operator=(const smart_ptr<T>& r) {alias(r); return *this;}
00276     ~smart_ptr(void) {}
00277   };
00278 
00279   ////////////////////////////////////////////////////////////////////////////////
00280   // smart_ptr_clone  for polymorphic class hierarchies which have a clone method
00281 
00282   template <typename T,typename COUNTER = mrpt::synch::CAtomicCounter>
00283   class smart_ptr_clone : public smart_ptr_base<T, clone_copy<T>, COUNTER >
00284   {
00285   public:
00286     smart_ptr_clone(void) {}
00287     explicit smart_ptr_clone(const T& data) : smart_ptr_base<T, clone_copy<T>, COUNTER >(data) {}
00288     explicit smart_ptr_clone(T* data) : smart_ptr_base<T, clone_copy<T>, COUNTER >(data) {}
00289     smart_ptr_clone<T>& operator=(const T& data) {set_value(data); return *this;}
00290     smart_ptr_clone<T>& operator=(const smart_ptr_clone<T>& r) {alias(r); return *this;}
00291     ~smart_ptr_clone(void) {}
00292   };
00293 
00294   ////////////////////////////////////////////////////////////////////////////////
00295   // smart_ptr_nocopy for any class that cannot or should not be copied
00296 
00297   template <typename T,typename COUNTER = mrpt::synch::CAtomicCounter>
00298   class smart_ptr_nocopy : public smart_ptr_base<T, no_copy<T>, COUNTER >
00299   {
00300   public:
00301     smart_ptr_nocopy(void) {}
00302     explicit smart_ptr_nocopy(const T& data) : smart_ptr_base<T, no_copy<T>, COUNTER >(data) {}
00303     explicit smart_ptr_nocopy(T* data) : smart_ptr_base<T, no_copy<T>, COUNTER >(data) {}
00304     smart_ptr_nocopy<T>& operator=(const T& data) {set_value(data); return *this;}
00305     smart_ptr_nocopy<T>& operator=(const smart_ptr_nocopy<T>& r) {alias(r); return *this;}
00306     ~smart_ptr_nocopy(void) {}
00307   };
00308 
00309   ////////////////////////////////////////////////////////////////////////////////
00310 
00311 } // end namespace stlplus
00312 
00313 #include "smart_ptr.tpp"
00314 #endif



Page generated by Doxygen 1.7.3 for MRPT 0.9.4 SVN:exported at Tue Jan 25 21:56:31 UTC 2011