halapi
hierarchichalalignmentformatapi
|
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