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