halapi hierarchichalalignmentformatapi

- Main Page
- Namespaces
- Classes
- Files

- File List

All Classes Namespaces Functions Pages
halCountedPtr.h
1 /*
2 * Copyright (C) 2012 by Glenn Hickey (hickey@soe.ucsc.edu)
3 *
4 * Released under the MIT license, see LICENSE.txt
5 */
6
7
30 #ifndef COUNTED_PTR_H
31 #define COUNTED_PTR_H
32
33 namespace hal {
34
35
36 template<typename X>
37 struct ptr_counter {
38 ptr_counter(X* p = 0, unsigned c = 1) : ptr(p), count(c) {}
39 X* ptr;
40 unsigned count;
41 };
42
43 template <class X>
44 class counted_ptr
45 {
46 public:
47 template <typename XX> friend class counted_ptr;
48 typedef ptr_counter<X> counter;
49
50 explicit counted_ptr(X* p = 0) // allocate a new counter
51 : itsCounter(0) {
52 if (p) itsCounter = new counter(p);
53 }
54
55 ~counted_ptr() {
56 release();
57 }
58
59 // important to keep the default copy constructor overloaded
60 // (even if the templated version below seems to cover it)
61 // to prevent the compiler from making its own and breaking everything
62 counted_ptr(const counted_ptr& r) {
63 acquire<X>(r.itsCounter);
64 }
65
66 // important to keep the default assignment operator overloaded
67 // (even if the templated version below seems to cover it)
68 // to prevent the compiler from making its own and breaking everything
69 counted_ptr& operator=(const counted_ptr& r) {
70 if (this != &r)
71 {
72 release();
73 acquire<X>(r.itsCounter);
74 }
75 return *this;
76 }
77
78 template <class Y>
79 counted_ptr(const counted_ptr<Y>& r) {
80 acquire<Y>(r.itsCounter);
81 }
82
83 template <class Y>
84 counted_ptr& operator=(const counted_ptr<Y>& r) {
85 if ((const void*)this != (const void*)(&r))
86 {
87 release();
88 acquire<Y>(r.itsCounter);
89 }
90 return *this;
91 }
92
93 X& operator*() const {return *itsCounter->ptr;}
94 X* operator->() const {return itsCounter->ptr;}
95 X* get() const {return itsCounter ? itsCounter->ptr : 0;}
96 bool unique() const {
97 return (itsCounter ? itsCounter->count == 1 : true);
98 }
99
100 private:
101
102 counter* itsCounter;
103
104 template <typename Y>
105 void acquire(ptr_counter<Y>* c) {
106 if (c) {
107 (void)static_cast<X*>(c->ptr);
108 itsCounter = reinterpret_cast<counter*>(c);
109 ++c->count;
110 }
111 else {
112 itsCounter = NULL;
113 }
114 }
115
116 void release() {
117 if (itsCounter) {
118 if (--itsCounter->count == 0) {
119 delete itsCounter->ptr;
120 delete itsCounter;
121 }
122 itsCounter = 0;
123 }
124 }
125 };
126
127 // need to specialize on constant template parameters so we can
128 // properly account for the const to non-const assignments. this is
129 // the only way i could figure out how to do it anyway, since the
130 // regular template just seems to understand types and not consts...
131 template <class X>
132 class counted_ptr<const X>
133 {
134 public:
135 template <typename XX> friend class counted_ptr;
136 typedef ptr_counter<const X> counter;
137
138 explicit counted_ptr(const X* p = 0) // allocate a new counter
139 : itsCounter(0) {
140 if (p) itsCounter = new counter(p);
141 }
142
143 ~counted_ptr() {
144 release();
145 }
146
147 // important to keep the default copy constructor overloaded
148 // (even if the templated version below seems to cover it)
149 // to prevent the compiler from making its own and breaking everything
150 counted_ptr(const counted_ptr<const X>& r) {
151 acquire<const X>(r.itsCounter);
152 }
153 counted_ptr(const counted_ptr<X>& r) {
154 acquire<const X>(reinterpret_cast<counter*>(r.itsCounter));
155 }
156
157 // important to keep the default assignment operator overloaded
158 // (even if the templated version below seems to cover it)
159 // to prevent the compiler from making its own and breaking everything
160 counted_ptr<const X>& operator=(const counted_ptr<const X>& r) {
161 if (this != &r)
162 {
163 release();
164 acquire<const X>(r.itsCounter);
165 }
166 return *this;
167 }
168 counted_ptr<const X>& operator=(
169 const counted_ptr<X>& r) {
170 return this->operator=(reinterpret_cast<const counted_ptr<const X>&>(r));
171 }
172
173 template <class Y>
174 counted_ptr(const counted_ptr<Y>& r) {
175 acquire<Y>(r.itsCounter);
176 }
177
178 template <class Y>
179 counted_ptr& operator=(const counted_ptr<Y>& r) {
180 if ((const void*)this != (const void*)(&r))
181 {
182 release();
183 acquire<Y>(r.itsCounter);
184 }
185 return *this;
186 }
187
188 const X& operator*() const {return *itsCounter->ptr;}
189 const X* operator->() const {return itsCounter->ptr;}
190 const X* get() const {return itsCounter ? itsCounter->ptr : 0;}
191 bool unique() const {
192 return (itsCounter ? itsCounter->count == 1 : true);
193 }
194
195 private:
196
197 counter* itsCounter;
198
199 template <typename Y>
200 void acquire(ptr_counter<Y>* c) {
201 if (c) {
202 (void)static_cast<const X*>(c->ptr);
203 itsCounter = reinterpret_cast<counter*>(c);
204 ++c->count;
205 }
206 else {
207 itsCounter = NULL;
208 }
209 }
210
211 void release() {
212 if (itsCounter) {
213 if (--itsCounter->count == 0) {
214 delete itsCounter->ptr;
215 delete itsCounter;
216 }
217 itsCounter = 0;
218 }
219 }
220 };
221
222
223 }
224 #endif // COUNTED_PTR_H