ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/utils/SmartPointer.hpp
Revision: 1492
Committed: Mon Aug 16 18:07:50 2010 UTC (14 years, 8 months ago) by chuckv
File size: 9368 byte(s)
Log Message:
Adding exception and reporting mechanism from ProtoMol to OpenMD.

File Contents

# User Rev Content
1 chuckv 1492 /*******************************************************************\
2    
3     Copyright (C) 2003 Joseph Coffland
4    
5     This program is free software; you can redistribute it and/or
6     modify it under the terms of the GNU General Public License
7     as published by the Free Software Foundation; either version 2
8     of the License, or (at your option) any later version.
9    
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     GNU General Public License for more details.
14    
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18     02111-1307, USA.
19    
20     For information regarding this software email
21     jcofflan@users.sourceforge.net
22    
23     \*******************************************************************/
24    
25     #include "utils/Exception.hpp"
26    
27     #ifndef UTILS_SMARTPOINTER_H
28     #define UTILS_SMARTPOINTER_H
29    
30     #include "utils/Counter.hpp"
31    
32     #include <stdlib.h>
33    
34    
35     namespace OpenMD {
36     // Forward Delcarations
37     class Exception;
38    
39     // Deallocators
40     template <class T>
41     struct SP_NEW {static void dealloc(T *ptr) {delete ptr;}};
42    
43     template <class T>
44     struct SP_ARRAY {static void dealloc(T *ptr) {delete [] ptr;}};
45    
46     struct SP_MALLOC {static void dealloc(void *ptr) {free(ptr);}};
47    
48     template <void (*Func)(void *)>
49     struct SP_FUNC {static void dealloc(void *ptr) {Func(ptr);}};
50    
51     /**
52     * This class is an implementation of a smart pointer. IT IS NOT
53     * THREAD SAFE. This means that you cannot use SmartPointers
54     * to the same data in different threads. Even if you make a new
55     * copy of the smart pointer. This is because they will still share
56     * the same Counter. However, SmartPointer
57     * is faster because it is not thread safe.
58     *
59     * You can use a SmartPointer on a dynamic instance of a class A as
60     * follows.
61     *
62     * SmartPointer<A> aPtr = new A;
63     *
64     * Since aPtr is static when it goes out of scope it will be destructed.
65     * When this happens the reference counter will be decremented and if
66     * it is zero the dynamic instance of A will be destructed.
67     *
68     * You can make a copy of a smart pointer as follows.
69     *
70     * SmartPointer<A> anotherPtr = aPtr;
71     *
72     * Now the dynamic instance of A will not be destructed until both
73     * aPtr and anotherPtr go out of scope.
74     *
75     * Correct deallocation can vary depending on the type of resource being
76     * protected by the smart pointer. The DEALLOC_T template parameter selects
77     * the deallocator. The default deallocator is used for any data allocated
78     * with the 'new' operator. SP_ARRAY is necessary for arrays allocated with
79     * the 'new []' operator. SP_MALLOC will correctly deallocate data allocated
80     * with calls to 'malloc', 'calloc', 'realloc', et.al.
81     *
82     * You can also create your own deallocators for other resources. The
83     * managed resources need not even be memory.
84     *
85     * See http://ootips.org/yonat/4dev/smart-pointers.html for more information
86     * about smart pointers and why to use them.
87     */
88     template <class T, class DEALLOC_T = SP_NEW<T> >
89     class SmartPointer {
90     /// A pointer to the reference counter.
91     Counter *refCounter;
92    
93     /// The actual pointer.
94     T *ptr;
95    
96     public:
97     typedef SmartPointer<T, DEALLOC_T> SmartPointer_T;
98     typedef SmartPointer<T, SP_ARRAY<T> > Array;
99    
100     /**
101     * Create a NULL smart pointer
102     *
103     */
104     SmartPointer() : refCounter(0), ptr(0) {}
105    
106     /**
107     * The copy constructor. If the smart pointer being copied
108     * is not NULL the object reference count will be incremented.
109     *
110     * @param smartPtr The pointer to copy.
111     */
112     SmartPointer(const SmartPointer_T &smartPtr) :
113     refCounter(0), ptr(0) {
114     *this = smartPtr;
115     }
116    
117     /**
118     * Create a smart pointer from a pointer value. If ptr is
119     * non-NULL the reference count will be set to one.
120     * NOTE: It is an error to create more than one smart pointer
121     * through this constructor for a single pointer value because
122     * this will cause the object
123     * to which it points to be deallocated more than once. To create
124     * a copy of a smart pointer either use the copy constructor or
125     * the smart pointer assignment operator.
126     *
127     * @param ptr The pointer to point to.
128     */
129     SmartPointer(T *ptr) : refCounter(0), ptr(0) {
130     if (ptr) {
131     refCounter = new Counter(1);
132     this->ptr = ptr;
133     }
134     }
135    
136     /**
137     * Destroy this smart pointer. If this smart pointer is set to
138     * a non-NULL value and there are no other references to the
139     * object to which it points the object will be deleted.
140     */
141     ~SmartPointer() {release();}
142    
143     /**
144     * Compare two smart pointers for equality. Two smart pointers
145     * are equal if and only if their internal pointers are equal.
146     *
147     * @param smartPtr The pointer to compare with.
148     *
149     * @return True if the smart pointers are equal. False otherwise.
150     */
151     const bool operator==(const SmartPointer_T &smartPtr) const {
152     return ptr == smartPtr.ptr;
153     }
154    
155    
156     /**
157     * Compare two smart pointers for inequality. Two smart pointers
158     * are not equal if and only if their internal pointers are not equal.
159     *
160     * @param smartPtr The pointer to compare with.
161     *
162     * @return True if the smart pointers are not equal. False otherwise.
163     */
164     const bool operator!=(const SmartPointer_T &smartPtr) const {
165     return ptr != smartPtr.ptr;
166     }
167    
168     /**
169     * Compare this smart pointer to an actual pointer value.
170     *
171     * @param ptr The pointer to compare with.
172     *
173     * @return True if this smart pointers internal pointer equals ptr.
174     * False otherwise.
175     */
176     const bool operator==(const T *ptr) {
177     return this->ptr == ptr;
178     }
179    
180     /**
181     * Asign this smart pointer to another. If the passed smart pointer
182     * is non-NULL a reference will be added.
183     *
184     * @param smartPtr The pointer to copy.
185     *
186     * @return A reference to this smart pointer.
187     */
188     SmartPointer_T &operator=(const SmartPointer_T &smartPtr) {
189     if (*this == smartPtr) return *this;
190    
191     release();
192    
193     refCounter = smartPtr.refCounter;
194     if (refCounter) refCounter->inc();
195     ptr = smartPtr.ptr;
196    
197     return *this;
198     }
199    
200     /**
201     * Dereference this smart pointer.
202     * A Exception will be thrown if this smart pointer is NULL.
203     *
204     * @return A reference to the object pointed to by this smart pointer.
205     */
206     T *operator->() const {checkPtr(); return get();}
207    
208     /**
209     * Dereference this smart pointer.
210     * A Exception will be thrown if this smart pointer is NULL.
211     *
212     * @return A reference to the object pointed to by this smart pointer.
213     */
214     T &operator*() const {checkPtr(); return *get();}
215    
216     /**
217     * Dereference this smart pointer with an array index.
218     * A Exception will be thrown if this smart pointer is NULL.
219     *
220     * @return A reference to an object in the array pointed to by
221     * this smart pointer.
222     */
223     T &operator[](const long x) const {checkPtr(); return get()[x];}
224    
225     /**
226     * Access this smart pointers internal object pointer;
227     *
228     * @return The value of the internal object pointer;
229     */
230     T *get() const {return ptr;}
231    
232     /// Not operator
233     bool operator!() const {return ptr == 0;}
234    
235     /**
236     * Release this smart pointer's reference.
237     * If the reference count is one the object to which this
238     * smart pointer points will be deleted.
239     */
240     void release() {
241     if (refCounter && !refCounter->dec()) {
242     delete refCounter;
243     DEALLOC_T::dealloc(ptr);
244     }
245    
246     refCounter = 0;
247     ptr = 0;
248     }
249    
250     /**
251     * Assume responsibility for this pointer. If the reference
252     * counter is more than one a Exception will be thrown.
253     * When successful this smart pointer will be NULL.
254     *
255     * This function can be useful for moving the pointer to
256     * a base class smart pointer.
257     *
258     * @return The value of the internal pointer.
259     */
260     T *adopt() {
261     if (refCounter && refCounter->getCount() > 1)
262     throw Exception
263     ("SmartPointer: Cannot adopt a pointer with multiple references!");
264    
265     if (refCounter) {
266     delete refCounter;
267     refCounter = 0;
268     }
269     T *tmp = ptr;
270     ptr = 0;
271    
272     return tmp;
273     }
274    
275     /**
276     * Get the number of references to the object pointed to by
277     * this smart pointer. The reference count will be zero
278     * if this is a NULL smart pointer other wise it will be
279     * one or more.
280     *
281     * @return The reference count.
282     */
283     long getRefCount() const {return refCounter ? refCounter->getCount() : 0;}
284    
285     /**
286     * Check for NULL pointer value;
287     *
288     * @return True if the internal pointer is NULL. False otherwise.
289     */
290     bool isNull() const {return get() == 0;}
291    
292     protected:
293     void checkPtr() const {
294     if (!ptr)
295     throw Exception("SmartPointer: Can't dereference a NULL pointer!");
296     }
297     };
298     }
299     #endif // SMARTPOINTER_H