smartptr.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005 Tommi Maekitalo
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27  */
28 
29 #ifndef CXXTOOLS_SMARTPTR_H
30 #define CXXTOOLS_SMARTPTR_H
31 
32 #include <cxxtools/atomicity.h>
33 
34 namespace cxxtools
35 {
39  template <typename ObjectType>
48  class RefLinked
49  {
50  mutable const RefLinked* prev;
51  mutable const RefLinked* next;
52 
53  protected:
55  : prev(0),
56  next(0)
57  { }
58 
60  bool unlink(ObjectType* object)
61  {
62  if (object)
63  {
64  if (next == this)
65  {
66  next = prev = 0;
67  return true;
68  }
69  else
70  {
71  next->prev = prev;
72  prev->next = next;
73  next = prev = this;
74  }
75  }
76  return false;
77  }
78 
80  void link(const RefLinked& ptr, ObjectType* object)
81  {
82  if (object)
83  {
84  if (ptr.next)
85  {
86  prev = &ptr;
87  next = ptr.next;
88  prev->next = this;
89  next->prev = this;
90  }
91  else
92  {
93  prev = next = this;
94  }
95  }
96  }
97 
98  };
99 
103  template <typename ObjectType>
113  {
114  protected:
116  bool unlink(ObjectType* object)
117  {
118  return object && object->release() == 0;
119  }
120 
122  void link(const InternalRefCounted& /*ptr*/, ObjectType* object)
123  {
124  if (object)
125  object->addRef();
126  }
127 
128  };
129 
133  template <typename ObjectType>
142  {
143  unsigned* rc;
144 
145  protected:
147  : rc(0) { }
148 
150  bool unlink(ObjectType* object)
151  {
152  if (object && --*rc <= 0)
153  {
154  delete rc;
155  rc = 0;
156  return true;
157  }
158  else
159  return false;
160  }
161 
163  void link(const ExternalRefCounted& ptr, ObjectType* object)
164  {
165  if (object)
166  {
167  if (ptr.rc == 0)
168  rc = new unsigned(1);
169  else
170  {
171  rc = ptr.rc;
172  ++*rc;
173  }
174  }
175  else
176  rc = 0;
177  }
178 
179  public:
180  unsigned refs() const
181  { return rc ? *rc : 0; }
182  };
183 
184  template <typename ObjectType>
186  {
187  volatile atomic_t* rc;
188 
189  protected:
191  : rc(0) { }
192 
193  bool unlink(ObjectType* object)
194  {
195  if (object && atomicDecrement(*rc) <= 0)
196  {
197  delete rc;
198  rc = 0;
199  return true;
200  }
201  else
202  return false;
203  }
204 
205  void link(const ExternalAtomicRefCounted& ptr, ObjectType* object)
206  {
207  if (object)
208  {
209  if (ptr.rc == 0)
210  rc = new atomic_t(1);
211  else
212  {
213  rc = ptr.rc;
214  atomicIncrement(*rc);
215  }
216  }
217  else
218  rc = 0;
219  }
220 
221  public:
222  atomic_t refs() const
223  { return rc ? atomicGet(*rc) : 0; }
224  };
225 
229  template <typename ObjectType>
236  {
237  public:
238  static void destroy(ObjectType* ptr)
239  { delete ptr; }
240  };
241 
245  template <typename ObjectType>
251  {
252  public:
253  static void destroy(ObjectType* ptr)
254  { delete ptr; }
255  };
256 
257  template <typename T>
259  {
260  public:
261  static void destroy(T* ptr)
262  { free(ptr); }
263  };
264 
265  template <typename ObjectType>
267  {
268  public:
269  static void destroy(ObjectType* ptr)
270  { delete[] ptr; }
271  };
272 
295  template <typename ObjectType,
296  template <class> class OwnershipPolicy = InternalRefCounted,
297  template <class> class DestroyPolicy = DefaultDestroyPolicy>
298  class SmartPtr : public OwnershipPolicy<ObjectType>,
299  public DestroyPolicy<ObjectType>
300  {
301  ObjectType* object;
302  typedef OwnershipPolicy<ObjectType> OwnershipPolicyType;
303  typedef DestroyPolicy<ObjectType> DestroyPolicyType;
304 
305  public:
307  : object(0)
308  {}
309  SmartPtr(ObjectType* ptr)
310  : object(ptr)
311  { OwnershipPolicyType::link(*this, ptr); }
312  SmartPtr(const SmartPtr& ptr)
313  : object(ptr.object)
314  { OwnershipPolicyType::link(ptr, ptr.object); }
315  template <typename T>
316  SmartPtr(const SmartPtr<T>& ptr)
317  : object(ptr.object)
318  { OwnershipPolicyType::link(ptr, ptr.object); }
320  { if (OwnershipPolicyType::unlink(object))
321  DestroyPolicy<ObjectType>::destroy(object); }
322 
324  {
325  if (object != ptr.object)
326  {
327  if (OwnershipPolicyType::unlink(object))
328  DestroyPolicy<ObjectType>::destroy(object);
329 
330  object = ptr.object;
331 
332  OwnershipPolicyType::link(ptr, object);
333  }
334  return *this;
335  }
336 
337  template <typename T>
339  {
340  if (object != ptr.object)
341  {
342  if (OwnershipPolicyType::unlink(object))
343  DestroyPolicy<ObjectType>::destroy(object);
344 
345  object = ptr.object;
346 
347  OwnershipPolicyType::link(ptr, object);
348  }
349  return *this;
350  }
351 
352  SmartPtr& operator= (ObjectType* ptr)
353  {
354  if (object != ptr)
355  {
356  if (OwnershipPolicyType::unlink(object))
357  DestroyPolicy<ObjectType>::destroy(object);
358 
359  object = ptr;
360 
361  OwnershipPolicyType::link(*this, ptr);
362  }
363  return *this;
364  }
365 
367  ObjectType* operator->() const { return object; }
369  ObjectType& operator*() const { return *object; }
370 
371  bool operator! () const { return object == 0; }
372  operator bool () const { return object != 0; }
373 
374  ObjectType* getPointer() const { return object; }
375  };
376 
377  template <typename T1, typename T2>
378  bool operator== (const SmartPtr<T1>& p1, const T2* p2)
379  { return p1.getPointer() == p2; }
380 
381  template <typename T1, typename T2>
382  bool operator== (const T1* p1, const SmartPtr<T2>& p2)
383  { return p1 == p2.getPointer(); }
384 
385  template <typename T1, typename T2>
386  bool operator== (const SmartPtr<T1>& p1, const SmartPtr<T2>& p2)
387  { return p1.getPointer() == p2.getPointer(); }
388 
389  template <typename T1, typename T2>
390  bool operator!= (const SmartPtr<T1>& p1, const T2* p2)
391  { return p1.getPointer() != p2; }
392 
393  template <typename T1, typename T2>
394  bool operator!= (const T1* p1, const SmartPtr<T2>& p2)
395  { return p1 != p2.getPointer(); }
396 
397  template <typename T1, typename T2>
398  bool operator!= (const SmartPtr<T1>& p1, const SmartPtr<T2>& p2)
399  { return p1.getPointer() != p2.getPointer(); }
400 
401 }
402 
403 #endif // CXXTOOLS_SMARTPTR_H
404