ref_ptr.hpp

Go to the documentation of this file.
00001 #ifndef wali_REF_PTR_GUARD
00002 #define wali_REF_PTR_GUARD 1
00003 
00004 /**
00005  * @author Nicholas Kidd
00006  * @author Evan Driscoll
00007  */
00008 
00009 #include <cstdio>
00010 #include <cassert>
00011 #include <climits>
00012 #include <iostream>
00013 
00014 namespace wali
00015 {
00016 
00017   /**
00018    * @class ref_ptr
00019    * @brief A reference counting pointer class
00020    * @warning This class is *NOT* thread safe.
00021    *
00022    * The templated class should use the mixin Countable. When using Countable
00023    * simply pass a boolean true or false to the rcmix constructor.  The default
00024    * value is true and this means the object will be reference counted.  A
00025    * passed in value of false means to not reference count the object (ie. it
00026    * will never be deleted ).
00027    *
00028    * If you prefer not to inherit from Countable, then the templated class 
00029    * must have a member variable named count that can be accessed from 
00030    * ref_ptr and modified by ref_ptr. the count variable should have
00031    * operator++(),operator--(), and operator==( int ) defined.  As a 
00032    * note, this class was designed with count being an unsigned integer.
00033    *
00034    * Count should be initialized to 0 for proper reference
00035    * couting to work.  If it is desirable for the pointer/object
00036    * to never be deleted, initialize count >= 1.  WARNING: don't forget
00037    * to initialize count to 0 in the copy constructor!  (And don't
00038    * forget to have a copy constructor.)
00039    *
00040    * @see Countable
00041    *
00042    */
00043 
00044   template< typename T > class ref_ptr
00045   {
00046 
00047     public:
00048       typedef unsigned int count_t;
00049 
00050       ref_ptr( T *t = 0 ) {
00051         acquire(t);
00052       }
00053 
00054       ref_ptr( const ref_ptr& rp ) {
00055         acquire( rp.ptr );
00056       }
00057 
00058       /**
00059        * @brief This will succeed if S is a subclass of T.
00060        */
00061       template< typename S > ref_ptr<T>( const ref_ptr<S>& rp ) {
00062         acquire( rp.get_ptr() );
00063       }
00064 
00065       ~ref_ptr() {
00066         release();
00067       }
00068 
00069       ref_ptr& operator=( T * t ) {
00070         if( ptr != t ) {
00071           T * old_ptr = ptr;
00072           acquire(t);
00073           release(old_ptr);
00074         }
00075         return *this;
00076       }
00077 
00078       ref_ptr& operator=( const ref_ptr& rp ) {
00079         return *this = rp.get_ptr();
00080       }
00081 
00082       bool operator==(const ref_ptr& that) const {
00083         return ptr == that.get_ptr();
00084       }
00085 
00086       bool operator!=(const ref_ptr& that) const {
00087         return ptr != that.get_ptr();
00088       }
00089 
00090       T * get_ptr() const {
00091         return ptr;
00092       }
00093 
00094       T * operator->() const {
00095         return ptr;
00096       }
00097 
00098       T& operator*()   const {
00099         assert(0 != ptr);
00100         return *ptr;
00101       }
00102 
00103       bool is_empty() const { return (0 == ptr); }
00104       bool is_valid() const { return !(is_empty());}
00105 
00106     private:
00107       T * ptr;
00108 
00109       void acquire( T * t )
00110       {
00111         ptr = t;
00112         if( t ) {
00113           ++t->count;
00114 #ifdef DBGREFPTR
00115           std::cout << "Acquired " << t << " with count = "
00116             << t->count << std::endl;
00117 #endif
00118         }
00119       }
00120 
00121       static void release( T * old_ptr )
00122       {
00123         if( old_ptr ) {
00124           --old_ptr->count;
00125 #ifdef DBGREFPTR
00126           std::cout << "Released " << *old_ptr << " with count = "
00127             << old_ptr->count << std::endl;
00128 #endif
00129           if( old_ptr->count == 0 ) {
00130 #ifdef DBGREFPTR
00131             std::cout << "Deleting ptr: " << *old_ptr << std::endl;
00132 #endif
00133             delete old_ptr;
00134           }
00135         }
00136       }
00137 
00138       void release() {
00139         release(ptr);
00140         ptr = 0;
00141       }
00142 
00143   }; // class ref_ptr
00144 
00145 } // namespace wali
00146 
00147 #endif  // wali_REF_PTR_GUARD
00148