source: tags/svn.1.5.4/TEMPLATES/smartptr.h

Last change on this file was 7811, checked in by westram, 14 years ago

merge from dev [7748] [7749] [7750]

  • comments (C→C++ style)
  • fixed umlauts in TREEGEN
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.4 KB
Line 
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 = 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
82template<class T, void (*DEALLOC)(T*)>
83class custom_dealloc_ptr : virtual Noncopyable {
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 : virtual Noncopyable {
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 : virtual Noncopyable {
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); // if you like to assign NULL, consider using SmartPtr::assign
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/*! @memo Smart pointer class
188 */
189
190template <class T, class C = Counted<T, auto_delete_ptr<T> > >
191class SmartPtr {
192private:
193    C *object;
194
195    void Unbind() {
196        if (object && object->free_reference()==0) {
197            DUMP_SMART_PTRS_DO(fprintf(stderr, "Unbind() deletes Counted object %p (which hold pointer %p)\n", object, object->getPointer()));
198            delete object;
199        }
200        object = 0;
201    }
202public:
203    //! build Smart-NULL-Ptr
204    SmartPtr() : object(0) {}
205
206    /*! build normal SmartPtr
207
208        by passing an object to a SmartPtr you loose the responsibility over the object
209        to the SmartPtr.
210        So you NEVER should free such an object manually.
211
212        @param p Pointer to any dynamically allocated object
213    */
214    SmartPtr(T *p) {
215        object = new C(p);
216        object->new_reference();
217    }
218
219    /*! destroy SmartPtr
220
221        object will not be destroyed as long as any other SmartPtr points to it
222    */
223    ~SmartPtr() { Unbind(); }
224
225    SmartPtr(const SmartPtr<T, C>& other) {
226        object = other.object;
227        if (object) object->new_reference();
228    }
229    SmartPtr<T, C>& operator=(const SmartPtr<T, C>& other) {
230        if (other.object) other.object->new_reference();
231        Unbind();
232        object = other.object;
233        return *this;
234    }
235   
236    const T *operator->() const { tpl_assert(object); return object->getPointer(); }
237    T *operator->() { tpl_assert(object); return object->getPointer(); }
238
239    const T& operator*() const { tpl_assert(object); return *(object->getPointer()); }
240    T& operator*() { tpl_assert(object); return *(object->getPointer()); } // Note: to deref a NULL-SmartPtr, use SmartPtr::content()
241
242    //! test if SmartPtr is NULL
243    bool isNull() const { return object == 0; }
244
245    //! test if SmartPtr is not NULL
246    bool isSet() const { return !isNull(); }
247
248    //! set SmartPtr to NULL
249    void SetNull() { Unbind(); }
250
251    //! set SmartPtr to new content or NULL
252    void assign(T *p) {
253        Unbind();
254        if (p) {
255            object = new C(p);
256            object->new_reference();
257        }
258    }
259
260    //! convert SmartPtr to plain old pointer (also works if isNull())
261    const T* content() const {
262        return object ? object->getPointer() : NULL;
263    }
264
265    SmartPtr<T, C> deep_copy() const {
266        /*! create a deep copy of the object pointed to by the smart pointer.
267         *
268         * Afterwards there exist two equal copies of the object.
269         *
270         * @return SmartPtr to the new copy.
271         */
272        return SmartPtr<T, C>(new T(**this));
273    }
274
275    bool sameObject(const SmartPtr<T, C>& other) const {
276        /*! test if two SmartPtrs point to the same object
277         *
278         * (this is used for operators == and !=).
279         *
280         * if you like to compare the objects themselves use
281         * (*smart_ptr1 == *smart_ptr2)
282         *
283         * @return true if the SmartPtrs point to the same object
284         */
285        tpl_assert(object);
286        tpl_assert(other.object);
287        return object==other.object;
288    }
289};
290
291template <class T, class C> bool operator==(const SmartPtr<T, C>& s1, const SmartPtr<T, C>& s2) {
292    return s1.sameObject(s2);
293}
294
295template <class T, class C> bool operator!=(const SmartPtr<T, C>& s1, const SmartPtr<T, C>& s2) {
296    return !s1.sameObject(s2);
297}
298
299// --------------------------
300//      convenience decls
301
302typedef SmartMallocPtr(char) SmartCharPtr;
303
304#define RETURN_LOCAL_ALLOC(mallocation)                         \
305    static SmartMallocPtr(typeof(*mallocation)) static_ptr;     \
306    static_ptr.assign(mallocation);                             \
307    return static_ptr.content();
308
309#define RETURN_ONETIME_ALLOC(allocated)                         \
310    static SmartMallocPtr(typeof(*allocated)) static_ptr;       \
311    if (static_ptr.isNull()) { static_ptr = allocated; }        \
312    return static_ptr.content();
313
314#else
315#error smartptr.h included twice
316#endif // SMARTPTR_H
Note: See TracBrowser for help on using the repository browser.