doxygen: intern/memutil tagged
[blender-staging.git] / intern / memutil / MEM_RefCountPtr.h
1 /*
2  * $Id$
3  * ***** BEGIN GPL 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.
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 Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file memutil/MEM_RefCountPtr.h
30  *  \ingroup memutil
31  */
32
33 /**
34  * @file        MEM_RefCountPtr.h
35  * Declaration of MEM_RefCounted and MEM_RefCountable classes.
36  * @author Laurence
37  */
38
39 #ifndef NAN_INCLUDED_MEM_RefCountPtr_h
40 #define NAN_INCLUDED_MEM_RefCountPtr_h
41
42 #include <stdlib.h> // for NULL !
43
44 /**
45  * @section MEM_RefCountable
46  * This is a base class for reference countable objects.
47  * If you want an object to be shared using a reference 
48  * counted system derrivce from this class. All subclasses
49  * should insist that they are created on the heap, this
50  * can be done by makeing all constructors private and 
51  * defining a static New() method that returns a ref counted
52  * ptr to a new()ly allocated instance. 
53  *
54  * @section Example subclass
55  *
56  *
57  * class MySharedObject : public MEM_RefCountable {
58  *
59  * private :
60  *      MySharedObject() : MEM_RefCountable() { //class specific initialization};
61  *  MySharedObject(const MySharedObject &other) // not implemented
62  * public :
63  *              static  
64  *                      MEM_RefCountPtr<MySharedObject> 
65  *              New(
66  *              ) {
67  *                      return MEM_RefCountPtr<MySharedObject>( new MySharedObject());
68  *              }
69  *              
70  *              // other member functions
71  * };
72  *
73  * Alternitively you may first wish to define a fully functional
74  * class and then define a reference counting wrapper for this class.
75  * This is useful when the base type can be used without reference
76  * counting.
77  *
78  * E.g.
79  * class UsefullClass {
80  * private :
81  *  ...
82  * public :
83  *
84  *      UsefullClass()
85  *      UsefullMethod(...)
86  *      AnotherUsefullMethod(...)
87  * };
88  *
89  * class RcUsefullClass : public UsefullClass, public MEM_RefCountable
90  * {
91  * private :
92  *      // Override base class public constructor --- forces
93  *      // use of New(...)
94  *      RcUsefullClass(...)
95  * public :
96  *
97  *  // Override each public constructor of UsefullClass with
98  *  // an equivalent static New method returning a MEM_RefCountPtr
99  *
100  *  static
101  *      MEM_RefCountPtr<RcUsefullClass>
102  *  New(...){
103  *       return MEM_RefCountPtr<RcUsefullClass> output(
104  *           new UsefullClass(...)
105  *       );
106  *   }
107  *
108  *  // warning never call destructor directly allow ref counting
109  *  // mechanism to handle object lifetime.
110  *  ~RcUsefullClass();
111  * };
112  *
113  *
114  */
115
116 class MEM_RefCountable {
117 private :
118
119         /**
120          * The reference count!
121          * We use mutable here because we would like to
122          * share references of const objects!
123          * Maybe should think about having decRef()
124          * another value because we should not be deleting
125          * non-const objects
126          */
127
128         mutable int m_count;
129
130 protected :
131
132         /**
133          * Protected constructors
134          * This class is not for direct instanciation. Sub classes
135          * should only be allocated on the heap.
136          */
137
138         MEM_RefCountable (
139         ) :
140                 m_count (0)
141         {
142         };
143
144         MEM_RefCountable (
145                 const MEM_RefCountable &
146         ) :
147                 m_count (0)
148         {
149         }
150
151 public :
152
153                 void
154         IncRef(
155         ) const {
156                 m_count++;
157         }
158
159                 int
160         DecRef(
161         ) {
162                 return (--m_count);
163         }
164
165         ~MEM_RefCountable(
166         ) {
167                 //nothing to do
168         }
169 };
170
171 /**
172  * @section MEM_RefCountPtr
173  */
174
175 template
176         < class T >
177 class MEM_RefCountPtr {
178
179 public :
180
181         /**
182          * Construction from reference - share ownership with
183          * the right hand side.
184          */
185
186         MEM_RefCountPtr(
187                 const MEM_RefCountPtr &rhs
188         ) : m_val (NULL) {
189                 ShareOwnership(rhs.m_val);
190         }
191
192         /**
193          * Construction from ptr - this class shares
194          * ownership of object val.
195          */
196
197         MEM_RefCountPtr(
198                 const T* val
199         ) :
200                 m_val (NULL)
201         {
202                 ShareOwnership(val);
203         }
204
205         /**
206          * Default constructor
207          */
208
209         MEM_RefCountPtr(
210         ) :
211                 m_val (NULL)
212         {
213         }
214
215         /**
216          * Type conversion from this class to the type
217          * of a pointer to the template parameter.
218          * This means you can pass an instance of this class
219          * to a function expecting a ptr of type T.
220          */
221
222         operator T * () const {
223                 return m_val;
224         }
225
226
227         MEM_RefCountPtr & operator=(
228                 const MEM_RefCountPtr &rhs
229         ) {
230                 if (this->m_val != rhs.m_val) {
231                         ReleaseOwnership();
232                         ShareOwnership(rhs.m_val);
233                 }
234                 return *this;
235         }
236
237         /**
238          * Overload the operator -> so that it's possible to access
239          * all the normal methods of the internal ptr.
240          */
241
242         T * operator->() const {
243                 return m_val;
244         }
245
246         /**
247          * Returrn a reference to the shared object.
248          */
249
250                 T&
251         Ref(
252         ) {
253                 return *m_val;
254         }
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