fixed spacing in the headers to get rid of some warnings and some other
[blender-staging.git] / intern / memutil / MEM_RefCountPtr.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_RefCountPtr_h
33
34 #define NAN_INCLUDED_MEM_RefCountPtr_h
35
36 /**
37  * $Id$
38  * Copyright (C) 2001 NaN Technologies B.V.
39  *
40  * @author Laurence
41  */
42
43 #include <stdlib.h> // for NULL !
44
45 /**
46  * @section MEM_RefCountable
47  * This is a base class for reference countable objects.
48  * If you want an object to be shared using a reference 
49  * counted system derrivce from this class. All subclasses
50  * should insist that they are created on the heap, this
51  * can be done by makeing all constructors private and 
52  * defining a static New() method that returns a ref counted
53  * ptr to a new()ly allocated instance. 
54  *
55  * @section Example subclass
56  *
57  *
58  * class MySharedObject : public MEM_RefCountable {
59  *
60  * private :
61  *      MySharedObject() : MEM_RefCountable() { //class specific initialization};
62  *  MySharedObject(const MySharedObject &other) // not implemented
63  * public :
64  *              static  
65  *                      MEM_RefCountPtr<MySharedObject> 
66  *              New(
67  *              ) {
68  *                      return MEM_RefCountPtr<MySharedObject>( new MySharedObject());
69  *              }
70  *              
71  *              // other member functions
72  * };
73  *
74  * Alternitively you may first wish to define a fully functional
75  * class and then define a reference counting wrapper for this class.
76  * This is useful when the base type can be used without reference
77  * counting.
78  *
79  * E.g.
80  * class UsefullClass {
81  * private :
82  *  ...
83  * public :
84  *
85  *      UsefullClass()
86  *      UsefullMethod(...)
87  *      AnotherUsefullMethod(...)
88  * };
89  *
90  * class RcUsefullClass : public UsefullClass, public MEM_RefCountable
91  * {
92  * private :
93  *      // Override base class public constructor --- forces
94  *      // use of New(...)
95  *      RcUsefullClass(...)
96  * public :
97  *
98  *  // Override each public constructor of UsefullClass with
99  *  // an equivalent static New method returning a MEM_RefCountPtr
100  *
101  *  static
102  *      MEM_RefCountPtr<RcUsefullClass>
103  *  New(...){
104  *       return MEM_RefCountPtr<RcUsefullClass> output(
105  *           new UsefullClass(...)
106  *       );
107  *   }
108  *
109  *  // warning never call destructor directly allow ref counting
110  *  // mechanism to handle object lifetime.
111  *  ~RcUsefullClass();
112  * };
113  *
114  *
115  */
116
117 class MEM_RefCountable {
118 private :
119
120         /**
121          * The reference count!
122          * We use mutable here because we would like to
123          * share references of const objects!
124          * Maybe should think about having decRef()
125          * another value because we should not be deleting
126          * non-const objects
127          */
128
129         mutable int m_count;
130
131 protected :
132
133         /**
134          * Protected constructors
135          * This class is not for direct instanciation. Sub classes
136          * should only be allocated on the heap.
137          */
138
139         MEM_RefCountable (
140         ) :
141                 m_count (0)
142         {
143         };
144
145         MEM_RefCountable (
146                 const MEM_RefCountable & other
147         ) :
148                 m_count (0)
149         {
150         }
151
152 public :
153
154                 void
155         IncRef(
156         ) const {
157                 m_count++;
158         }
159
160                 int
161         DecRef(
162         ) {
163                 return (--m_count);
164         }
165
166         ~MEM_RefCountable(
167         ) {
168                 //nothing to do
169         }
170 };
171
172 /**
173  * @section MEM_RefCountPtr
174  */
175
176 template
177         < class T >
178 class MEM_RefCountPtr {
179
180 public :
181
182         /**
183          * Construction from reference - share ownership with
184          * the right hand side.
185          */
186
187         MEM_RefCountPtr(
188                 const MEM_RefCountPtr &rhs
189         ) : m_val (NULL) {
190                 ShareOwnership(rhs.m_val);
191         }
192
193         /**
194          * Construction from ptr - this class shares
195          * ownership of object val.
196          */
197
198         MEM_RefCountPtr(
199                 const T* val
200         ) :
201                 m_val (NULL)
202         {
203                 ShareOwnership(val);
204         }
205
206         /**
207          * Defalut constructor
208          */
209
210         MEM_RefCountPtr(
211         ) :
212                 m_val (NULL)
213         {
214         }
215
216         /**
217          * Type conversion from this class to the type
218          * of a pointer to the template parameter.
219          * This means you can pass an instance of this class
220          * to a function expecting a ptr of type T.
221          */
222
223         operator T * () const {
224                 return m_val;
225         }
226
227
228         MEM_RefCountPtr & operator=(
229                 const MEM_RefCountPtr &rhs
230         ) {
231                 if (this->m_val != rhs.m_val) {
232                         ReleaseOwnership();
233                         ShareOwnership(rhs.m_val);
234                 }
235                 return *this;
236         }
237
238         /**
239          * Overload the operator -> so that it's possible to access
240          * all the normal methods of the internal ptr.
241          */
242
243         T * operator->() const {
244                 return m_val;
245         }
246
247         /**
248          * Returrn a reference to the shared object.
249          */
250
251                 T&
252         Ref(
253         ) {
254                 return *m_val;
255         }
256
257         /**
258          * Destructor - deletes object if it's ref count is zero.
259          */
260
261         ~MEM_RefCountPtr(
262         ) {
263                 ReleaseOwnership();
264         }
265
266 private :
267         
268         /// The ptr owned by this class.
269         T * m_val;
270
271                 void
272         ShareOwnership(
273                 const T * val
274         ) {
275                 if (val != NULL) {
276                         val->IncRef();
277                 }
278                 m_val = const_cast<T *>(val);
279         }
280                 
281                 void
282         ReleaseOwnership(
283         ) {
284                 if (m_val) {
285                         if (m_val->DecRef() == 0) {
286                                 delete(m_val);
287                                 m_val = NULL;
288                         }
289                 }
290         }
291
292 };
293
294 #endif
295