Object-oriented Scientific Computing Library: Version 0.910
shared_ptr.h
00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2011-2012, Andrew W. Steiner
00005   
00006   This file is part of O2scl. It was adapted from the shared_ptr
00007   implementation of aegis, available at aegis.sourceforge.net.
00008   
00009   O2scl is free software; you can redistribute it and/or modify
00010   it under the terms of the GNU General Public License as published by
00011   the Free Software Foundation; either version 3 of the License, or
00012   (at your option) any later version.
00013   
00014   O2scl is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017   GNU General Public License for more details.
00018   
00019   You should have received a copy of the GNU General Public License
00020   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00021 
00022   -------------------------------------------------------------------
00023 */
00024 //
00025 // aegis - project change supervisor
00026 // Copyright (C) 2007, 2008 Peter Miller
00027 //
00028 // This program is free software; you can redistribute it and/or
00029 // modify it under the terms of the GNU General Public License 
00030 // as published by the Free Software Foundation; either version 3 
00031 // of the License, or (at your option) any later version.
00032 //
00033 // This program is distributed in the hope that it will be useful,
00034 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00035 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00036 // GNU General Public License for more details.
00037 //
00038 // You should have received a copy of the GNU General Public 
00039 // License along with this program. If not, see
00040 // <http://www.gnu.org/licenses/>.
00041 
00042 #ifndef O2SCL_SHARED_PTR_H
00043 #define O2SCL_SHARED_PTR_H
00044 
00045 #include <cassert>
00046 
00047 #ifndef DOXYGENP
00048 namespace o2scl {
00049 #endif
00050 
00051   /** \brief The internal shared pointer class used if no TR1 or Boost
00052       implementation is available
00053 
00054       See also \ref o2_shared_ptr . 
00055 
00056       This class was based on the Aegis <tt>shared_ptr</tt> class from
00057       http:://aegis.sourceforge.net, but is implemented in \o2 using a
00058       template struct rather than a define constant.
00059   */
00060   template<class T> class o2_int_shared_ptr {
00061 
00062   private:
00063 
00064     /** \brief Reference count
00065 
00066         Documentation from Aegis:
00067         \verbatim
00068         The reference_count instance variable is used to remember the
00069         location of the reference count. By having the reference count
00070         separate from the subject, we can cope with compatible pointers,
00071         not just exact pointers.
00072       
00073         This is not ideal because it allocates huge numbers of small
00074         objects. Some heap implementations go slowly when faced with
00075         many small allocations. Some heap implementations waste a lot of
00076         memory when faced with many small allocations.
00077         \endverbatim
00078     */
00079     long *reference_count;
00080 
00081     /** \brief Object being pointed to
00082 
00083         Documentation from Aegis:
00084         \verbatim
00085         The subject instance variable is used to remember the location
00086         of the object being reference counted.  By having it separate
00087         from the reference count, we can skip one indirection.
00088         \endverbatim
00089     */
00090     T *subject;
00091 
00092   public:
00093 
00094     /** \brief Create an empty shared_ptr
00095      */
00096     o2_int_shared_ptr() : reference_count(0),subject(0) {
00097       assert(valid());
00098     }
00099   
00100     /** \brief Create a shared pointer
00101       
00102         This constructor permits initialization from any compatable
00103         pointer where \c Y must be a complete type. 
00104     */
00105     template<class Y> explicit o2_int_shared_ptr(Y *rhs) :
00106     reference_count(0), subject(0) {
00107       assert(valid());
00108       if (rhs) {
00109         reference_count = new long(1);
00110         subject = rhs;
00111       }
00112       assert(valid());
00113     }
00114   
00115     ~o2_int_shared_ptr() {
00116       assert(valid());
00117       if (reference_count) {
00118         --*reference_count;
00119         if (*reference_count <= 0) {
00120           delete subject;
00121           subject = 0;
00122           delete reference_count;
00123           reference_count = 0;
00124         }
00125       }
00126     }
00127   
00128     /** \brief Copy constructor.
00129      */
00130   o2_int_shared_ptr(const o2_int_shared_ptr &rhs) :
00131     reference_count(0), subject(0) {
00132       assert(rhs.valid());
00133       if (rhs.subject) {
00134         assert(rhs.reference_count);
00135         reference_count = rhs.reference_count;
00136         subject = rhs.subject;
00137         ++*reference_count;
00138       }
00139       assert(valid());
00140     }
00141   
00142     template <class Y> friend class o2_int_shared_ptr;
00143   
00144     /** \brief Copy constructor for compatible pointer types
00145      */
00146     template<class Y> o2_int_shared_ptr(const o2_int_shared_ptr<Y> &rhs) :
00147     reference_count(0), subject(0) {
00148       assert(rhs.valid());
00149       if (rhs.subject) {
00150         assert(rhs.reference_count);
00151         reference_count = rhs.reference_count;
00152         subject = rhs.subject;
00153         ++*reference_count;
00154       }
00155       assert(valid());
00156     }
00157   
00158     /** \brief Test if the shared_ptr object is valid
00159       
00160         This method verifies that the internal state of 
00161         the shared pointer object is valid.
00162     */
00163     bool valid() const {
00164       return ((reference_count != 0) ? (*reference_count > 0 && 
00165                                         subject != 0) : (subject == 0));
00166     }
00167   
00168     /** \brief Swap
00169 
00170         Swap the contents of two o2_int_shared_ptr<T> objects.
00171         This method is more efficient than manually swapping 
00172         shared_ptr objects using a copy constructor or temporary.
00173     */
00174     void swap(o2_int_shared_ptr &rhs) {
00175       assert(valid());
00176       assert(rhs.valid());
00177       long *temp_reference_count = reference_count;
00178       T *temp_subject = subject;
00179       reference_count = rhs.reference_count;
00180       subject = rhs.subject;
00181       rhs.reference_count = temp_reference_count;
00182       rhs.subject = temp_subject;
00183     }
00184 
00185     /** \brief Drop the reference and set the pointer to zero
00186      */
00187     void reset() {
00188       // swap with a NULL pointer
00189       o2_int_shared_ptr tmp;
00190       this->swap(tmp);
00191     }
00192 
00193     /** \brief Assignment operator
00194      */
00195     o2_int_shared_ptr &operator=(const o2_int_shared_ptr &rhs) {
00196       assert(valid());
00197       assert(rhs.valid());
00198       if (this != &rhs) {
00199         // Documentation from Aegis:
00200         // 
00201         // In case you haven't seen the swap() technique to
00202         // implement copy assignment before, here's what it does:
00203         //
00204         // 1) Create a temporary o2_int_shared_ptr<> instance via the
00205         //    copy constructor, thereby increasing the reference
00206         //    count of the source object.
00207         //
00208         // 2) Swap the internal object pointers of *this and the
00209         //    temporary o2_int_shared_ptr<>.  After this step, *this
00210         //    already contains the new pointer, and the old pointer
00211         //    is now managed by temp.
00212         //
00213         // 3) The destructor of temp is executed, thereby
00214         //    unreferencing the old object pointer.
00215         //
00216         // This technique is described in Herb Sutter's "Exceptional
00217         // C++", and has a number of advantages over conventional
00218         // approaches:
00219         //
00220         // - Code reuse by calling the copy constructor.
00221         // - Strong exception safety for free.
00222         // - Self assignment is handled implicitly.
00223         // - Simplicity.
00224         // - It just works and is hard to get wrong; i.e. you can
00225         //   use it without even thinking about it to implement
00226         //   copy assignment where ever the object data is managed
00227         //   indirectly via a pointer, which is very common.
00228         //
00229         o2_int_shared_ptr temp(rhs);
00230         this->swap(temp);
00231         assert(valid());
00232         assert(rhs.valid());
00233       }
00234       return *this;
00235     }
00236 
00237     /** \brief Assignment operator for compatible pointer types
00238      */
00239     template<class Y> o2_int_shared_ptr &operator=
00240       (const o2_int_shared_ptr<Y> &rhs) {
00241       assert(valid());
00242       assert(rhs.valid());
00243       if (this != (o2_int_shared_ptr *)&rhs) {
00244         o2_int_shared_ptr tmp(rhs);
00245         this->swap(tmp);
00246         assert(valid());
00247         assert(rhs.valid());
00248       }
00249       return *this;
00250     }
00251   
00252     /** \brief Dereference operator 
00253      */
00254     T &operator*() const {
00255       assert(subject != 0);
00256       return *subject;
00257     }
00258 
00259     /** \brief Pointing at operator
00260      */
00261     T *operator->() const {
00262       assert(subject != 0);
00263       return subject;
00264     }
00265     
00266     /** \brief Return a pointer to the object
00267      */
00268     T *get() const {
00269       return subject;
00270     }
00271 
00272     /** \brief Return true if the pointer is not zero.
00273      */
00274     operator bool() const {
00275       return (subject != 0);
00276     }
00277 
00278     /** \brief Logical not operator
00279         
00280         Return true if and only if the pointer is zero.
00281     */
00282     bool operator!() const {
00283       return (subject == 0);
00284     }
00285 
00286     /** \brief Test equality
00287      */
00288     inline bool operator==(const o2_int_shared_ptr &rhs) const {
00289       return (subject == rhs.get());
00290     }
00291 
00292     /** \brief Test equality for compatible pointer types
00293      */
00294     template<class U> inline bool operator==
00295       (const o2_int_shared_ptr<U> &rhs) const {
00296       return (subject == rhs.get());
00297     }
00298 
00299     /** \brief Test inequality
00300      */
00301     inline bool operator!=(o2_int_shared_ptr &rhs) const {
00302       return (subject != rhs.get());
00303     }
00304 
00305     /** \brief Test inequality for compatible pointer types
00306      */
00307     template<class U> inline bool operator!=(o2_int_shared_ptr<U> &rhs) const {
00308       return (subject != rhs.get());
00309     }
00310 
00311     /** \brief Less than operator
00312      */
00313     inline bool operator<(o2_int_shared_ptr &rhs) const {
00314       return (subject < rhs.get());
00315     }
00316 
00317     /** \brief Less than operator for compatible pointer types
00318      */
00319     template<class U> inline bool operator<(o2_int_shared_ptr<U> &rhs) const {
00320       return (subject < rhs.get());
00321     }
00322 
00323   };
00324 
00325 #ifndef DOXYGENP
00326 }
00327 #endif
00328 
00329 #ifdef DOXYGENP
00330 
00331 /** \brief A struct to provide the shared_ptr type
00332 
00333     This object exists in order to provide the shared_ptr template
00334     type used in \o2. The full specification of a shared pointer
00335     in \o2 for an object of type \c T is thus 
00336     \verbatim
00337     o2scl::o2_shared_ptr<T>::type
00338     \endverbatim
00339     In a default \o2 installation, \ref type (as given below)
00340     is a typedef of
00341     \verbatim
00342     std::tr1::shared_ptr<T>
00343     \endverbatim
00344     If <tt>O2SCL_NO_TR1_MEMORY</tt> is defined, then \ref type is
00345     a typedef of \ref o2_int_shared_ptr, unless <tt>O2SCL_HAVE_BOOST</tt>
00346     is defined, in which case \ref type is a typedef of
00347     \verbatim
00348     boost::shared_ptr<T>
00349     \endverbatim
00350 
00351     See also the discussion at http://www.gotw.ca/gotw/079.htm . This
00352     struct won't be necessary when C++ allows template typedef's as
00353     part of the C++11 standard http://en.wikipedia.org/wiki/C%2B%2B11
00354     , but very few compilers have implemented this standard yet.
00355 */
00356 template<class T> struct o2_shared_ptr {
00357   /// The actual shared_ptr type
00358   typedef std::tr1::shared_ptr<T> type;
00359 };
00360 
00361 #else
00362 
00363 // -------------------------------------------------------------------
00364 // Define the o2_shared_ptr struct according to the installation settings
00365 
00366 // AWS - 11/29/11: I can't remember if the #include statements have
00367 // to be outside the o2scl namespace, but I make sure they're
00368 // outside just in case it matters.
00369 
00370 #ifndef O2SCL_NO_TR1_MEMORY
00371 
00372 #include <tr1/memory>
00373 namespace o2scl {
00374   template<class T> struct o2_shared_ptr {
00375     typedef std::tr1::shared_ptr<T> type;
00376   };
00377 }
00378 
00379 #else
00380 
00381 #if O2SCL_HAVE_BOOST
00382 
00383 #include <boost/shared_ptr.hpp>
00384 namespace o2scl {
00385   template<class T> struct o2_shared_ptr {
00386     typedef boost::shared_ptr<T> type;
00387   };
00388 }
00389 
00390 #else
00391 
00392 namespace o2scl {
00393   template<class T> struct o2_shared_ptr {
00394     typedef o2_int_shared_ptr<T> type;
00395   };
00396 }
00397 
00398 // end of if O2SCL_HAVE_BOOST
00399 #endif
00400 
00401 // end of if O2SCL_NO_TR1_MEMORY
00402 #endif
00403 
00404 // end of ifdef DOXYGENP
00405 #endif
00406 
00407 // -------------------------------------------------------------------
00408 
00409 // end of ifdef O2SCL_SHARED_PTR_H
00410 #endif 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.