halapi
hierarchichalalignmentformatapi
inc/counted_ptr.h
00001 /*
00002  * Copyright (C) 2012 by Glenn Hickey (hickey@soe.ucsc.edu)
00003  *
00004  * Released under the MIT license, see LICENSE.txt
00005  */
00006 
00007 
00018 /*
00019  * counted_ptr - simple reference counted pointer.
00020  *
00021  * The is a non-intrusive implementation that allocates an additional
00022  * int and pointer for every counted object.
00023  */
00024 
00025 #ifndef COUNTED_PTR_H
00026 #define COUNTED_PTR_H
00027 
00028 /* For ANSI-challenged compilers, you may want to #define
00029  * NO_MEMBER_TEMPLATES or explicit */
00030 
00031 namespace hal {
00032 
00033 template <typename T>
00034 struct counted_ptr_remove_const
00035 {
00036     typedef T type;
00037 };
00038 template <typename T>
00039 struct counted_ptr_remove_const<const T>
00040 {
00041     typedef T type;
00042 };
00043 
00044 template<typename X>
00045 struct ptr_counter {
00046    ptr_counter(X* p = 0, unsigned c = 1) : ptr(p), count(c) {}
00047    X*          ptr;
00048    unsigned    count;
00049 }; 
00050 
00051 template<typename X>
00052 struct ptr_counter<const X> {
00053    ptr_counter(const X* p = 0, unsigned c = 1) : ptr(p), count(c) {}
00054    const X*          ptr;
00055    unsigned    count;
00056    
00057    ptr_counter& operator=(const ptr_counter<typename counted_ptr_remove_const<X>::type>& other) {
00058      ptr = other.ptr;
00059      count = other.count;
00060    }
00061 };
00062 template <class X> class counted_ptr
00063 {
00064 public:
00065    friend class counted_ptr<const X>;
00066    typedef X element_type;
00067    typedef ptr_counter<X> counter;
00068 
00069     explicit counted_ptr(X* p = 0) // allocate a new counter
00070       : itsCounter(0) {if (p) itsCounter = new counter(p);}
00071     ~counted_ptr()
00072         {release();}
00073     counted_ptr(const counted_ptr& r) throw()
00074         {acquire(r.itsCounter);}
00075     counted_ptr& operator=(const counted_ptr& r)
00076     {
00077         if (this != &r) {
00078             release();
00079             acquire(r.itsCounter);
00080         }
00081         return *this;
00082     }
00083  
00084 
00085 
00086     /*
00087 #ifndef NO_MEMBER_TEMPLATES
00088     template <class Y> friend class counted_ptr<Y>;
00089     template <class Y> counted_ptr(const counted_ptr<Y>& r) throw()
00090         {acquire(r.itsCounter);}
00091     template <class Y> counted_ptr& operator=(const counted_ptr<Y>& r)
00092     {
00093         if (this != &r) {
00094             release();
00095             acquire(r.itsCounter);
00096         }
00097         return *this;
00098     }
00099 #endif // NO_MEMBER_TEMPLATES
00100     */
00101 
00102     X& operator*()  const throw()   {return *itsCounter->ptr;}
00103     X* operator->() const throw()   {return itsCounter->ptr;}
00104     X* get()        const throw()   {return itsCounter ? itsCounter->ptr : 0;}
00105     bool unique()   const throw()
00106         {return (itsCounter ? itsCounter->count == 1 : true);}
00107 
00108 private:
00109 
00110    counter* itsCounter;
00111 
00112     void acquire(counter* c) throw()
00113     { // increment the count
00114         itsCounter = c;
00115         if (c) ++c->count;
00116     }
00117 
00118     void release()
00119     { // decrement the count, delete if it is 0
00120         if (itsCounter) {
00121             if (--itsCounter->count == 0) {
00122                 delete itsCounter->ptr;
00123                 delete itsCounter;
00124             }
00125             itsCounter = 0;
00126         }
00127     }
00128 };
00129 
00130 
00131 template <class X> class counted_ptr<const X>
00132 {
00133 public:
00134     typedef const X element_type;
00135    typedef ptr_counter<const X> counter;
00136 
00137     explicit counted_ptr(const X* p = 0) // allocate a new counter
00138         : itsCounter(0) {if (p) itsCounter = new counter(p);}
00139    ~counted_ptr()
00140         {release();}
00141     counted_ptr(const counted_ptr& r) throw()
00142         {acquire(r.itsCounter);}
00143     counted_ptr& operator=(const counted_ptr& r)
00144     {
00145         if (this != &r) {
00146             release();
00147             acquire(r.itsCounter);
00148         }
00149         return *this;
00150     }
00151 
00152    counted_ptr(const counted_ptr<typename counted_ptr_remove_const<X>::type>& r) throw()
00153       {acquire(r.itsCounter);}
00154    counted_ptr& operator=(const counted_ptr<typename counted_ptr_remove_const<X>::type>& r)
00155    {
00156      if (this != &r) {
00157        release();
00158        acquire(r.itsCounter);
00159      }
00160      return *this;
00161    }
00162 /*
00163 #ifndef NO_MEMBER_TEMPLATES
00164     template <class Y> friend class counted_ptr<Y>;
00165     template <class Y> counted_ptr(const counted_ptr<Y>& r) throw()
00166         {acquire(r.itsCounter);}
00167     template <class Y> counted_ptr& operator=(const counted_ptr<Y>& r)
00168     {
00169         if (this != &r) {
00170             release();
00171             acquire(r.itsCounter);
00172         }
00173         return *this;
00174     }
00175 #endif // NO_MEMBER_TEMPLATES
00176 */
00177     const X& operator*()  const throw()   {return *itsCounter->ptr;}
00178     const X* operator->() const throw()   {return itsCounter->ptr;}
00179     const X* get()        const throw()   {return itsCounter ? itsCounter->ptr : 0;}
00180     bool unique()   const throw()
00181         {return (itsCounter ? itsCounter->count == 1 : true);}
00182 
00183 private:
00184 
00185    counter* itsCounter;
00186 
00187     void acquire(counter* c) throw()
00188     { // increment the count
00189         itsCounter = c;
00190         if (c) ++c->count;
00191     }
00192 
00193     void acquire(ptr_counter<typename counted_ptr_remove_const<X>::type>* c) throw()
00194     { // increment the count
00195       itsCounter = (ptr_counter<const X>*)c;
00196         if (c) ++c->count;
00197     }
00198 
00199     void release()
00200     { // decrement the count, delete if it is 0
00201         if (itsCounter) {
00202             if (--itsCounter->count == 0) {
00203                 delete itsCounter->ptr;
00204                 delete itsCounter;
00205             }
00206             itsCounter = 0;
00207         }
00208     }
00209 };
00210 }
00211 #endif // COUNTED_PTR_H
 All Classes Namespaces Functions