Yes I did it again ;)
[blender.git] / intern / memutil / MEM_SmartPtr.h
1 /**
2  * $Id$
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
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. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  */
31
32 #ifndef NAN_INCLUDED_MEM_SmartPtr_h
33 #define NAN_INCLUDED_MEM_SmartPtr_h
34
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 /**
40  * $Id$
41  * Copyright (C) 2001 NaN Technologies B.V.
42  *
43  * @author Laurence
44  */
45
46 #include <stdlib.h> // for NULL !
47
48 /**
49  * @section MEM_SmartPtr 
50  * This class defines a smart pointer similar to that defined in 
51  * the Standard Template Library but without the painful get()
52  * semantics to access the internal c style pointer.
53  *
54  * It is often useful to explicitely decalre ownership of memory
55  * allocated on the heap within class or function scope. This
56  * class helps you to encapsulate this ownership within a value
57  * type. When an instance of this class goes out of scope it
58  * makes sure that any memory associated with it's internal pointer
59  * is deleted. It can help to inform users of an aggregate class
60  * that it owns instances of it's members and these instances 
61  * should not be shared. This is not reliably enforcable in C++
62  * but this class attempts to make the 1-1 relationship clear.
63  * 
64  * @section Example usage
65  *
66  * class foo {
67  *              ...constructors accessors etc.
68  *              int x[1000];
69  * }
70  * 
71  * class bar {
72  *  public :
73  *              static
74  *                      bar *
75  *              New(
76  *              ) {
77  *                      MEM_SmartPtr<foo> afoo = new foo();
78  *                      MEM_SmartPtr<bar> that = new bar();
79  *
80  *                      if (foo == NULL || that == NULL) return NULL;
81  *
82  *                      that->m_foo = afoo.Release();
83  *                      return that.Release();
84  *              }
85  *
86  *              ~bar() {
87  *                      // smart ptr takes care of deletion
88  *              }
89  *      private :
90  *              MEM_SmartPtr<foo> m_foo;
91  *      }
92  *                      
93  * You my also safely construct vectors of MEM_SmartPtrs and 
94  * have the vector own stuff you put into it. 
95  *
96  * e.g.
97  * { 
98  * std::vector<MEM_SmartPtr<foo> > foo_vector;
99  * foo_vector.push_back( new foo());
100  * foo_vector.push_back( new foo());
101  *
102  * foo_vector[0]->bla();
103  * } // foo_vector out of scope => heap memory freed for both foos
104  *
105  * @warning this class should only be used for objects created
106  * on the heap via the new function. It will not behave correctly
107  * if you pass ptrs to objects created with new[] nor with 
108  * objects declared on the stack. Doing this is likely to crash
109  * the program or lead to memory leaks.
110  */
111
112 template 
113         < class T >
114 class MEM_SmartPtr {
115
116 public :
117
118         /**
119          * Construction from reference - this class
120          * always assumes ownership from the rhs.
121          */
122
123         MEM_SmartPtr(
124                 const MEM_SmartPtr &rhs
125         ){
126                 m_val = rhs.Release();
127         }
128
129         /**
130          * Construction from ptr - this class always
131          * assumes that it now owns the memory associated with the
132          * ptr.
133          */
134
135         MEM_SmartPtr(
136                 T* val
137         ) :
138                 m_val (val)
139         {
140         }
141         
142         /**
143          * Defalut constructor
144          */
145
146         MEM_SmartPtr(
147         ) :
148                 m_val (NULL)
149         {
150         }
151
152         /**
153          * Type conversion from this class to the type
154          * of a pointer to the template parameter. 
155          * This means you can pass an instance of this class
156          * to a function expecting a ptr of type T.
157          */
158
159         operator T * () const {
160                 return m_val;
161         }
162
163         /**
164          * Return a reference to the internal ptr class.
165          * Use with care when you now that the internal ptr
166          * is not NULL!
167          */
168
169                 T &
170         Ref(
171         ) const {
172                 return *m_val;
173         }       
174
175         /** 
176          * Assignment operator - ownership is transfered from rhs to lhs. 
177          * There is an intenional side-effect of function of transferring
178          * ownership from the const parameter rhs. This is to insure 
179          * the 1-1 relationship.
180          * The object associated with this instance is deleted if it 
181          * is not the same as that contained in the rhs.
182          */
183
184         MEM_SmartPtr & operator=(
185                 const MEM_SmartPtr &rhs
186         ) {
187                 if (this->m_val != rhs.m_val) {
188                         delete this->m_val;
189                 }
190
191                 this->m_val = rhs.Release();
192                 return *this;
193         }
194         
195         /** 
196          * Overload the operator -> so that it's possible to access
197          * all the normal methods of the internal ptr. 
198          */
199         
200         T * operator->() const {
201                 return m_val;
202         }
203
204         /**
205          * Caller takes ownership of the object - the object will not 
206          * be deleted when the ptr goes out of scope.
207          */
208
209                 T *
210         Release(
211         ) const {
212                 T* temp = m_val;
213                 (const_cast<MEM_SmartPtr *>(this))->m_val = NULL;       
214                 return temp;
215         }
216
217         /**
218          * Force destruction of the internal object.
219          */
220         
221                 void
222         Delete(
223         ) {
224                 delete (m_val);
225                 m_val = NULL;
226         }
227
228         /** 
229          * Destructor - deletes object if it exists
230          */
231
232         ~MEM_SmartPtr(
233         ) {
234                 delete (m_val);
235         }
236
237 private :
238         
239         /// The ptr owned by this class.
240         T * m_val;
241 };
242
243 #endif
244