]> Dogcows Code - chaz/yoink/blob - smart_ptr.tpp
cb1b8bbb825886754779bebcf2aabcc0980a793a
[chaz/yoink] / smart_ptr.tpp
1 ////////////////////////////////////////////////////////////////////////////////
2
3 // Author: Andy Rushton
4 // Copyright: (c) Southampton University 1999-2004
5 // (c) Andy Rushton 2004-2009
6 // License: BSD License, see ../docs/license.html
7
8 ////////////////////////////////////////////////////////////////////////////////
9
10 namespace stlplus
11 {
12
13 ////////////////////////////////////////////////////////////////////////////////
14 // internal holder data structure
15 ////////////////////////////////////////////////////////////////////////////////
16
17 template<typename T>
18 class smart_ptr_holder
19 {
20 private:
21 unsigned m_count;
22 T* m_data;
23
24 // make these private to disallow copying because the holder doesn't know how to copy
25 smart_ptr_holder(const smart_ptr_holder& s) :
26 m_count(0), m_data(0)
27 {
28 }
29
30 smart_ptr_holder& operator=(const smart_ptr_holder& s)
31 {
32 return *this;
33 }
34
35 public:
36 smart_ptr_holder(T* p = 0) :
37 m_count(1), m_data(p)
38 {
39 }
40
41 ~smart_ptr_holder(void)
42 {
43 clear();
44 }
45
46 unsigned count(void) const
47 {
48 return m_count;
49 }
50
51 void increment(void)
52 {
53 ++m_count;
54 }
55
56 bool decrement(void)
57 {
58 --m_count;
59 return m_count == 0;
60 }
61
62 bool null(void)
63 {
64 return m_data == 0;
65 }
66
67 void clear(void)
68 {
69 if(m_data)
70 delete m_data;
71 m_data = 0;
72 }
73
74 void set(T* p = 0)
75 {
76 clear();
77 m_data = p;
78 }
79
80 T*& pointer(void)
81 {
82 return m_data;
83 }
84
85 const T* pointer(void) const
86 {
87 return m_data;
88 }
89
90 T& value(void)
91 {
92 return *m_data;
93 }
94
95 const T& value(void) const
96 {
97 return *m_data;
98 }
99 };
100
101 ////////////////////////////////////////////////////////////////////////////////
102 // smart_ptr_base class
103 ////////////////////////////////////////////////////////////////////////////////
104
105 ////////////////////////////////////////////////////////////////////////////////
106 // constructors, assignments and destructors
107
108 // create a null pointer
109 template <typename T, typename C>
110 smart_ptr_base<T,C>::smart_ptr_base(void) :
111 m_holder(new smart_ptr_holder<T>)
112 {
113 }
114
115 // create a pointer containing a *copy* of the object pointer
116 template <typename T, typename C>
117 smart_ptr_base<T,C>::smart_ptr_base(const T& data) throw(illegal_copy) :
118 m_holder(new smart_ptr_holder<T>)
119 {
120 m_holder->set(C()(data));
121 }
122
123 // create a pointer containing a dynamically created object
124 // Note: the object must be allocated *by the user* with new
125 // constructor form - must be called in the form smart_ptr<type> x(new type(args))
126 template <typename T, typename C>
127 smart_ptr_base<T,C>::smart_ptr_base(T* data) :
128 m_holder(new smart_ptr_holder<T>)
129 {
130 m_holder->set(data);
131 }
132
133 // copy constructor implements counted referencing - no copy is made
134 template <typename T, typename C>
135 smart_ptr_base<T,C>::smart_ptr_base(const smart_ptr_base<T,C>& r) :
136 m_holder(0)
137 {
138 m_holder = r.m_holder;
139 m_holder->increment();
140 }
141
142 // destructor decrements the reference count and delete only when the last reference is destroyed
143 template <typename T, typename C>
144 smart_ptr_base<T,C>::~smart_ptr_base(void)
145 {
146 if(m_holder->decrement())
147 delete m_holder;
148 }
149
150 //////////////////////////////////////////////////////////////////////////////
151 // logical tests to see if there is anything contained in the pointer since it can be null
152
153 template <typename T, typename C>
154 bool smart_ptr_base<T,C>::null(void) const
155 {
156 return m_holder->null();
157 }
158
159 template <typename T, typename C>
160 bool smart_ptr_base<T,C>::present(void) const
161 {
162 return !m_holder->null();
163 }
164
165 template <typename T, typename C>
166 bool smart_ptr_base<T,C>::operator!(void) const
167 {
168 return m_holder->null();
169 }
170
171 template <typename T, typename C>
172 smart_ptr_base<T,C>::operator bool(void) const
173 {
174 return !m_holder->null();
175 }
176
177 //////////////////////////////////////////////////////////////////////////////
178 // dereference operators and functions
179
180 template <typename T, typename C>
181 T& smart_ptr_base<T,C>::operator*(void) throw(null_dereference)
182 {
183 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
184 return m_holder->value();
185 }
186
187 template <typename T, typename C>
188 const T& smart_ptr_base<T,C>::operator*(void) const throw(null_dereference)
189 {
190 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
191 return m_holder->value();
192 }
193
194 template <typename T, typename C>
195 T* smart_ptr_base<T,C>::operator->(void) throw(null_dereference)
196 {
197 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
198 return m_holder->pointer();
199 }
200
201 template <typename T, typename C>
202 const T* smart_ptr_base<T,C>::operator->(void) const throw(null_dereference)
203 {
204 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
205 return m_holder->pointer();
206 }
207
208 //////////////////////////////////////////////////////////////////////////////
209 // explicit function forms of the above assignment dereference operators
210
211 template <typename T, typename C>
212 void smart_ptr_base<T,C>::set_value(const T& data) throw(illegal_copy)
213 {
214 m_holder->set(C()(data));
215 }
216
217 template <typename T, typename C>
218 T& smart_ptr_base<T,C>::value(void) throw(null_dereference)
219 {
220 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
221 return m_holder->value();
222 }
223
224 template <typename T, typename C>
225 const T& smart_ptr_base<T,C>::value(void) const throw(null_dereference)
226 {
227 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
228 return m_holder->value();
229 }
230
231 template <typename T, typename C>
232 void smart_ptr_base<T,C>::set(T* data)
233 {
234 m_holder->set(data);
235 }
236
237 template <typename T, typename C>
238 T* smart_ptr_base<T,C>::pointer(void)
239 {
240 return m_holder->pointer();
241 }
242
243 template <typename T, typename C>
244 const T* smart_ptr_base<T,C>::pointer(void) const
245 {
246 return m_holder->pointer();
247 }
248
249 ////////////////////////////////////////////////////////////////////////////////
250 // functions to manage counted referencing
251
252 // make this an alias of the passed object
253 template <typename T, typename C>
254 void smart_ptr_base<T,C>::alias(const smart_ptr_base<T,C>& r)
255 {
256 // make it alias-copy safe - this means that I don't try to do the
257 // assignment if r is either the same object or an alias of it
258 // if (m_holder == r.m_holder) return;
259 // if (m_holder->decrement())
260 // delete m_holder;
261 // m_holder = r.m_holder;
262 // m_holder->increment();
263 make_alias(r.m_holder);
264 }
265
266 template <typename T, typename C>
267 bool smart_ptr_base<T,C>::aliases(const smart_ptr_base<T,C>& r) const
268 {
269 return m_holder == r.m_holder;
270 }
271
272 template <typename T, typename C>
273 unsigned smart_ptr_base<T,C>::alias_count(void) const
274 {
275 return m_holder->count();
276 }
277
278 template <typename T, typename C>
279 void smart_ptr_base<T,C>::clear(void)
280 {
281 m_holder->clear();
282 }
283
284 template <typename T, typename C>
285 void smart_ptr_base<T,C>::clear_unique(void)
286 {
287 if (m_holder->count() == 1)
288 m_holder->clear();
289 else
290 {
291 m_holder->decrement();
292 m_holder = 0;
293 m_holder = new smart_ptr_holder<T>;
294 }
295 }
296
297 template <typename T, typename C>
298 void smart_ptr_base<T,C>::make_unique(void) throw(illegal_copy)
299 {
300 if (m_holder->count() > 1)
301 {
302 smart_ptr_holder<T>* old_holder = m_holder;
303 m_holder->decrement();
304 m_holder = 0;
305 m_holder = new smart_ptr_holder<T>;
306 if (old_holder->pointer())
307 m_holder->set(C()(old_holder->value()));
308 }
309 }
310
311 template <typename T, typename C>
312 void smart_ptr_base<T,C>::copy(const smart_ptr_base<T,C>& data) throw(illegal_copy)
313 {
314 alias(data);
315 make_unique();
316 }
317
318 // internal function for distinguishing unique smart_ptr objects
319 // used for example in persistence routines
320
321 template <typename T, typename C>
322 void* smart_ptr_base<T,C>::handle(void) const
323 {
324 return m_holder;
325 }
326
327 template <typename T, typename C>
328 void smart_ptr_base<T,C>::make_alias(void* handle)
329 {
330 smart_ptr_holder<T>* r_holder = (smart_ptr_holder<T>*)handle;
331 if (m_holder != r_holder)
332 {
333 if (m_holder->decrement())
334 delete m_holder;
335 m_holder = r_holder;
336 m_holder->increment();
337 }
338 }
339
340 ////////////////////////////////////////////////////////////////////////////////
341
342 } // end namespace stlplus
343
This page took 0.051909 seconds and 3 git commands to generate.