ARB
smartptr.h
Go to the documentation of this file.
1 // --------------------------------------------------------------------------------
2 // Copyright (C) 2000-2003
3 // Ralf Westram
4 // (Coded@ReallySoft.de)
5 //
6 // Permission to use, copy, modify, distribute and sell this software
7 // and its documentation for any purpose is hereby granted without fee,
8 // provided that the above copyright notice appear in all copies and
9 // that both that copyright notice and this permission notice appear
10 // in supporting documentation. Ralf Westram makes no
11 // representations about the suitability of this software for any
12 // purpose. It is provided "as is" without express or implied warranty.
13 //
14 // This code is part of my library.
15 // You may find a more recent version at http://www.reallysoft.de/
16 // --------------------------------------------------------------------------------
17 
18 #ifndef SMARTPTR_H
19 #define SMARTPTR_H
20 
21 #ifndef ARB_ASSERT_H
22 #include <arb_assert.h>
23 #endif
24 #ifndef ARBTOOLS_H
25 #include "arbtools.h"
26 #endif
27 
28 #define tpl_assert(bed) arb_assert(bed)
29 
30 // --------------------------------------------------------------------------------
31 // SmartPointers
32 // --------------------------------------------------------------------------------
33 //
34 // provides:
35 //
36 // SmartPtr<type> uses delete
37 // SmartPtr<type, Counted<type, auto_delete_array_ptr<type> > > uses delete []
38 // SmartPtr<type, Counted<type, auto_free_ptr<type> > > uses free
39 // SmartPtr<type, Counted<type, custom_dealloc_ptr<type, deallocator> > > uses custom deallocator
40 //
41 // --------------------------------------------------------------------------------
42 // macros for convenience:
43 
44 #define SmartArrayPtr(type) SmartPtr<type, Counted<type, auto_delete_array_ptr<type> > >
45 #define SmartMallocPtr(type) SmartPtr<type, Counted<type, auto_free_ptr<type> > >
46 #define SmartCustomPtr(type, deallocator) SmartPtr<type, Counted<type, custom_dealloc_ptr<type, deallocator> > >
47 
48 // --------------------------------------------------------------------------------
49 // examples:
50 //
51 // typedef SmartPtr<std::string> StringPtr;
52 // StringPtr s = new std::string("hello world"); // will be deallocated using delete
53 //
54 // typedef SmartArrayPtr(std::string) StringArrayPtr;
55 // StringArrayPtr strings = new std::string[100]; // will be deallocated using delete []
56 //
57 // SmartCharPtr cp = ARB_strdup("hello world"); // will be deallocated using free()
58 //
59 // typedef SmartCustomPtr(GEN_position, GEN_free_position) GEN_position_Ptr;
60 // GEN_position_Ptr gp = GEN_new_position(5, false); // will be deallocated using GEN_free_position()
61 //
62 // --------------------------------------------------------------------------------
63 
64 #ifdef NDEBUG
65 #ifdef DUMP_SMART_PTRS
66 #error Please do not define DUMP_SMART_PTRS in NDEBUG mode!
67 #endif
68 #endif
69 
70 #ifdef DUMP_SMART_PTRS
71 #define DUMP_SMART_PTRS_DO(cmd) do { (cmd); } while (0)
72 #else
73 #define DUMP_SMART_PTRS_DO(cmd)
74 #endif
75 
76 // -----------------------------------------------------------------
77 // helper pointer classes
78 //
79 // used by Counted<> to use correct method to destroy the contents
80 // -----------------------------------------------------------------
81 
82 template<class T, void (*DEALLOC)(T*)>
84  T *const thePointer;
85 public:
86  custom_dealloc_ptr(T *p) : thePointer(p) {
87  DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p now controlled by custom_dealloc_ptr\n", thePointer));
88  }
90  DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p gets destroyed by custom_dealloc_ptr (using fun %p)\n", thePointer, DEALLOC));
91  DEALLOC(thePointer);
92  }
93 
94  const T* getPointer() const { return thePointer; }
95  T* getPointer() { return thePointer; }
96 };
97 
98 template <class T>
99 class auto_free_ptr : virtual Noncopyable {
100  T *const thePointer;
101 public:
102  auto_free_ptr(T *p) : thePointer(p) {
103  DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p now controlled by auto_free_ptr\n", thePointer));
104  }
106  DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p gets destroyed by auto_free_ptr\n", thePointer));
107  free(thePointer);
108  }
109 
110  const T* getPointer() const { return thePointer; }
111  T* getPointer() { return thePointer; }
112 };
113 
114 template <class T>
115 class auto_delete_ptr : virtual Noncopyable {
116  T *const thePointer;
117 public:
118  auto_delete_ptr(T *p) : thePointer(p) {
119  DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p now controlled by auto_delete_ptr\n", thePointer));
120  }
122  DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p gets destroyed by auto_delete_ptr\n", thePointer));
123  delete thePointer;
124  }
125 
126  const T* getPointer() const { return thePointer; }
127  T* getPointer() { return thePointer; }
128 };
129 
130 template <class T>
132  T *const thePointer;
133 public:
134  auto_delete_array_ptr(T *p) : thePointer(p) {
135  DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p now controlled by auto_delete_array_ptr\n", thePointer));
136  }
138  DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p gets destroyed by auto_delete_array_ptr\n", thePointer));
139  delete [] thePointer;
140  }
141 
142  const T* getPointer() const { return thePointer; }
143  T* getPointer() { return thePointer; }
144 };
145 
146 // -----------------------
147 // class Counted
148 
149 template <class T, class C> class SmartPtr;
150 
151 template <class T, class AP>
152 class Counted {
153  unsigned counter;
154  AP pointer;
155 
156 public:
157 
158  Counted(T *p) : counter(0), pointer(p) {
159  DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p now controlled by Counted\n", getPointer()));
160  tpl_assert(p); // if you like to assign NULp, consider using SmartPtr::assign or SmartPtr::setNull
161  }
162 #ifdef DEBUG
163  ~Counted() {
164  tpl_assert(counter==0);
165  DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p gets destroyed by Counted\n", getPointer()));
166  }
167 #endif
168 
169  unsigned new_reference() {
170  DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p gets new reference (now there are %i references)\n", getPointer(), counter+1));
171  return ++counter;
172  }
173  unsigned free_reference() {
174  DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p looses a reference (now there are %i references)\n", getPointer(), counter-1));
175  tpl_assert(counter!=0);
176  return --counter;
177  }
178 
179  const T* getPointer() const { return pointer.getPointer(); }
180  T* getPointer() { return pointer.getPointer(); }
181 
182  friend class SmartPtr<T, Counted<T, AP> >;
183 };
184 
185 
190 template <class T, class C = Counted<T, auto_delete_ptr<T> > >
191 // cppcheck-suppress noCopyConstructor (does not detect templated cctor)
192 class SmartPtr {
193 private:
194  C *object;
195 
196  void Unbind() {
197  if (object && object->free_reference()==0) {
198  DUMP_SMART_PTRS_DO(fprintf(stderr, "Unbind() deletes Counted object %p (which hold pointer %p)\n", object, object->getPointer()));
199  delete object;
200  }
201  object = NULp;
202  }
203 public:
205  SmartPtr() : object(NULp) {}
206 
215  SmartPtr(T *p) {
216  object = new C(p);
217  object->new_reference();
218  }
219 
224  ~SmartPtr() { Unbind(); }
225 
226  SmartPtr(const SmartPtr<T, C>& other) {
227  // cppcheck-suppress copyCtorPointerCopying (that's exactly what a SmartPtr is made for)
228  object = other.object;
229  if (object) object->new_reference();
230  }
232  if (other.object) other.object->new_reference();
233  Unbind();
234  object = other.object;
235  return *this;
236  }
237 
238  const T *operator->() const { tpl_assert(object); return object->getPointer(); }
239  T *operator->() { tpl_assert(object); return object->getPointer(); }
240 
241  const T& operator*() const { tpl_assert(object); return *(object->getPointer()); }
242  T& operator*() { tpl_assert(object); return *(object->getPointer()); } // Note: to deref a NULp-SmartPtr, use SmartPtr::content()
243 
245  bool isSet() const { return object; }
246 
248  bool isNull() const { return !isSet(); }
249 
251  void setNull() { Unbind(); }
252 
254  void assign(T *p) {
255  Unbind();
256  if (p) {
257  object = new C(p);
258  object->new_reference();
259  }
260  }
261 
263  const T* content() const {
264  return object ? object->getPointer() : NULp;
265  }
266 
274  return SmartPtr<T, C>(new T(**this));
275  }
276 
277  bool sameObject(const SmartPtr<T, C>& other) const {
287  tpl_assert(object);
288  tpl_assert(other.object);
289  return object==other.object;
290  }
291 
292  unsigned references() const {
293  return isSet() ? object->counter : 0;
294  }
295 };
296 
297 template <class T, class C> bool operator==(const SmartPtr<T, C>& s1, const SmartPtr<T, C>& s2) {
298  return s1.sameObject(s2);
299 }
300 
301 template <class T, class C> bool operator!=(const SmartPtr<T, C>& s1, const SmartPtr<T, C>& s2) {
302  return !s1.sameObject(s2);
303 }
304 
305 // --------------------------
306 // convenience decls
307 
308 typedef SmartMallocPtr(char) SmartCharPtr;
309 
310 #define RETURN_LOCAL_ALLOC(mallocation) \
311  static SmartMallocPtr(typeof(*mallocation)) static_ptr; \
312  static_ptr.assign(mallocation); \
313  return static_ptr.content();
314 
315 #define RETURN_ONETIME_ALLOC(allocated) \
316  static SmartMallocPtr(typeof(*allocated)) static_ptr; \
317  if (static_ptr.isNull()) { static_ptr = allocated; } \
318  return static_ptr.content();
319 
320 #else
321 #error smartptr.h included twice
322 #endif // SMARTPTR_H
~SmartPtr()
Definition: smartptr.h:224
auto_delete_array_ptr(T *p)
Definition: smartptr.h:134
T * getPointer()
Definition: smartptr.h:111
T * getPointer()
Definition: smartptr.h:127
unsigned references() const
Definition: smartptr.h:292
const T * getPointer() const
Definition: smartptr.h:126
const T * getPointer() const
Definition: smartptr.h:179
const T * getPointer() const
Definition: smartptr.h:142
bool operator==(const SmartPtr< T, C > &s1, const SmartPtr< T, C > &s2)
Definition: smartptr.h:297
SmartPtr(T *p)
Definition: smartptr.h:215
#define tpl_assert(bed)
Definition: smartptr.h:28
T * getPointer()
Definition: smartptr.h:180
bool isNull() const
test if SmartPtr is NULp
Definition: smartptr.h:248
const T * getPointer() const
Definition: smartptr.h:94
unsigned new_reference()
Definition: smartptr.h:169
auto_delete_ptr(T *p)
Definition: smartptr.h:118
void setNull()
set SmartPtr to NULp
Definition: smartptr.h:251
T & operator*()
Definition: smartptr.h:242
SmartPtr< T, C > & operator=(const SmartPtr< T, C > &other)
Definition: smartptr.h:231
const T * getPointer() const
Definition: smartptr.h:110
bool isSet() const
test if SmartPtr is not NULp
Definition: smartptr.h:245
Generic smart pointer.
Definition: smartptr.h:149
#define SmartMallocPtr(type)
Definition: smartptr.h:45
Counted(T *p)
Definition: smartptr.h:158
custom_dealloc_ptr(T *p)
Definition: smartptr.h:86
const T * content() const
convert SmartPtr to plain old pointer (also works if isNull())
Definition: smartptr.h:263
SmartPtr()
build Smart-NULp-Ptr
Definition: smartptr.h:205
bool operator!=(const SmartPtr< T, C > &s1, const SmartPtr< T, C > &s2)
Definition: smartptr.h:301
unsigned free_reference()
Definition: smartptr.h:173
const T & operator*() const
Definition: smartptr.h:241
Definition: trnsprob.h:20
SmartPtr< T, C > deep_copy() const
Definition: smartptr.h:267
auto_free_ptr(T *p)
Definition: smartptr.h:102
#define NULp
Definition: cxxforward.h:97
bool sameObject(const SmartPtr< T, C > &other) const
Definition: smartptr.h:277
void assign(T *p)
set SmartPtr to new content or NULp
Definition: smartptr.h:254
Definition: trnsprob.h:20
SmartPtr(const SmartPtr< T, C > &other)
Definition: smartptr.h:226
#define DUMP_SMART_PTRS_DO(cmd)
Definition: smartptr.h:73
const T * operator->() const
Definition: smartptr.h:238
T * operator->()
Definition: smartptr.h:239