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