source: tags/arb_5.3/TEMPLATES/smartptr.h

Last change on this file was 5809, checked in by westram, 15 years ago
  • added template custom_dealloc_ptr≠ providing smartpointers with custom deallocation function
  • fixed compilation of smartpointer trace code
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 KB
Line 
1/////////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2000-2003
4// Ralf Westram
5// (Coded@ReallySoft.de)
6//
7// Permission to use, copy, modify, distribute and sell this software
8// and its documentation for any purpose is hereby granted without fee,
9// provided that the above copyright notice appear in all copies and
10// that both that copyright notice and this permission notice appear
11// in supporting documentation.  Ralf Westram makes no
12// representations about the suitability of this software for any
13// purpose.  It is provided "as is" without express or implied warranty.
14//
15// This code is part of my library.
16// You may find a more recent version at http://www.reallysoft.de/
17//
18/////////////////////////////////////////////////////////////////////////////
19
20#ifndef SMARTPTR_H
21#define SMARTPTR_H
22
23#ifndef ARB_ASSERT_H
24#include <arb_assert.h>
25#endif
26#define tpl_assert(bed) arb_assert(bed)
27
28// --------------------------------------------------------------------------------
29//     SmartPointers
30// --------------------------------------------------------------------------------
31//
32//  provides:
33//
34//  SmartPtr<type>                                                              uses delete
35//  SmartPtr<type, Counted<type, auto_delete_array_ptr<type> > >                uses delete []
36//  SmartPtr<type, Counted<type, auto_free_ptr<type> > >                        uses free
37//  SmartPtr<type, Counted<type, custom_dealloc_ptr<type, deallocator> > >      uses custom deallocator
38//
39// --------------------------------------------------------------------------------
40// macros for convinience:
41
42#define SmartArrayPtr(type)               SmartPtr<type, Counted<type, auto_delete_array_ptr<type> > >
43#define SmartMallocPtr(type)              SmartPtr<type, Counted<type, auto_free_ptr<type> > >
44#define SmartCustomPtr(type, deallocator) SmartPtr<type, Counted<type, custom_dealloc_ptr<type, deallocator> > >
45
46// --------------------------------------------------------------------------------
47// examples:
48//
49// typedef SmartPtr<std::string> StringPtr;
50// StringPtr s = new std::string("hello world");        // will be deallocated using delete
51//
52// typedef SmartArrayPtr(std::string) StringArrayPtr;
53// StringArrayPtr strings = new std::string[100];       // will be deallocated using delete []
54//
55// typedef SmartMallocPtr(char) CharPtr;
56// CharPtr cp = strdup("hello world");                  // will be deallocated using free()
57//
58// typedef SmartCustomPtr(GEN_position, GEN_free_position) GEN_position_Ptr;
59// GEN_position_Ptr gp = GEN_new_position(5, GB_FALSE); // will be deallocated using GEN_free_position()
60//
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
82template<class T, void (*DEALLOC)(T*)>
83class custom_dealloc_ptr {
84    T *const thePointer;
85public:
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    }
89    ~custom_dealloc_ptr() {
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
98template <class T>
99class auto_free_ptr {
100    T *const thePointer;
101public:
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    }
105    ~auto_free_ptr() {
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
114template <class T>
115class auto_delete_ptr {
116    T *const thePointer;
117public:
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    }
121    ~auto_delete_ptr() {
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
130template <class T>
131class auto_delete_array_ptr {
132    T *const thePointer;
133public:
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    }
137    ~auto_delete_array_ptr() {
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
150template <class T, class C> class SmartPtr;
151
152template <class T, class AP>
153class Counted {
154    unsigned counter;
155    AP       pointer;
156
157public:
158
159    Counted(T *p) : counter(0), pointer(p) {
160        DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p now controlled by Counted\n", getPointer()));
161        tpl_assert(p);
162    }
163#ifdef DEBUG
164    ~Counted() {
165        tpl_assert(counter==0);
166        DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p gets destroyed by Counted\n", getPointer()));
167    }
168#endif
169
170    unsigned new_reference() {
171        DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p gets new reference (now there are %i references)\n", getPointer(), counter+1));
172        return ++counter;
173    }
174    unsigned free_reference() {
175        DUMP_SMART_PTRS_DO(fprintf(stderr, "pointer %p looses a reference (now there are %i references)\n", getPointer(), counter-1));
176        tpl_assert(counter!=0);
177        return --counter;
178    }
179
180    const T* getPointer() const { return pointer.getPointer(); }
181    T* getPointer() { return pointer.getPointer(); }
182
183    friend class SmartPtr<T, Counted<T, AP> >;
184};
185
186
187// --------------------------------------------------------------------------------
188//     class SmartPtr
189// --------------------------------------------------------------------------------
190/** @memo Smart pointer class
191     */
192
193template <class T, class C = Counted<T, auto_delete_ptr<T> > >
194class SmartPtr {
195private:
196    C *object;
197
198    void Unbind() {
199        if (object && object->free_reference()==0) {
200            DUMP_SMART_PTRS_DO(fprintf(stderr, "Unbind() deletes Counted object %p (which hold pointer %p)\n", object, object->getPointer()));
201            delete object;
202        }
203        object = 0;
204    }
205public:
206    /** build Smart-NULL-Ptr */
207    SmartPtr() : object(0) {}
208
209    /** build normal SmartPtr
210
211        by passing an object to a SmartPtr you loose the responsibility over the object
212        to the SmartPtr.
213        So you NEVER should free such an object manually.
214
215        @param p Pointer to any dynamically allocated object
216    */
217    SmartPtr(T *p) {
218        object = new C(p);
219        object->new_reference();
220    }
221
222    /** destroy SmartPtr
223
224        object will not be destroyed as long as any other SmartPtr points to it
225    */
226    ~SmartPtr() { Unbind(); }
227
228    SmartPtr(const SmartPtr<T, C>& other) {
229        object = other.object;
230        if (object) object->new_reference();
231    }
232    SmartPtr<T, C>& operator=(const SmartPtr<T, C>& other) {
233        if (other.object) other.object->new_reference();
234        Unbind();
235        object = other.object;
236        return *this;
237    }
238
239    const T *operator->() const { tpl_assert(object); return object->getPointer(); }
240    T *operator->() { tpl_assert(object); return object->getPointer(); }
241
242    const T& operator*() const { tpl_assert(object); return *(object->getPointer()); }
243    T& operator*() { tpl_assert(object); return *(object->getPointer()); }
244
245    /** test if SmartPtr is 0 */
246    bool Null() const { return object==0; }
247
248    /** set SmartPtr to 0 */
249    void SetNull() { Unbind(); }
250
251    /** create a deep copy of the object pointed to by the smart pointer.
252
253        Afterwards there exist two equal copies of the object.
254
255        @return SmartPtr to the new copy.
256    */
257    SmartPtr<T, C> deep_copy() const { return SmartPtr<T, C>(new T(**this)); }
258
259    /** test if two SmartPtrs point to the same object
260        (this is used for operators == and !=).
261
262        if you like to compare the objects themselves use
263        (*smart_ptr1 == *smart_ptr2)
264
265        @return true if the SmartPtrs point to the same object
266    */
267    bool sameObject(const SmartPtr<T, C>& other) const {
268        tpl_assert(object);
269        tpl_assert(other.object);
270        return object==other.object;
271    }
272};
273
274template <class T, class C> bool operator==(const SmartPtr<T, C>& s1, const SmartPtr<T, C>& s2) {
275    return s1.sameObject(s2);
276}
277
278template <class T, class C> bool operator!=(const SmartPtr<T, C>& s1, const SmartPtr<T, C>& s2) {
279    return !s1.sameObject(s2);
280}
281
282#else
283#error smartptr.h included twice
284#endif // SMARTPTR_H
Note: See TracBrowser for help on using the repository browser.