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