add new sigc++2 directory
[ardour.git] / libs / glibmm2 / glib / glibmm / refptr.h
1 // -*- c++ -*-
2 #ifndef _GLIBMM_REFPTR_H
3 #define _GLIBMM_REFPTR_H
4
5 /* $Id: refptr.h 216 2005-04-07 08:28:46Z murrayc $ */
6
7 /* Copyright 2002 The gtkmm Development Team
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the Free
21  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24
25 namespace Glib
26 {
27
28 /** RefPtr<> is a reference-counting shared smartpointer.
29  *
30  * Some objects in gtkmm are obtained from a shared
31  * store. Consequently you cannot instantiate them yourself. Instead they
32  * return a RefPtr which behaves much like an ordinary pointer in that members
33  * can be reached with the usual <code>object_ptr->member</code> notation.
34  * Unlike most other smart pointers, RefPtr doesn't support dereferencing
35  * through <code>*object_ptr</code>.
36  *
37  * Reference counting means that a shared reference count is incremented each
38  * time a RefPtr is copied, and decremented each time a RefPtr is destroyed,
39  * for instance when it leaves its scope. When the reference count reaches
40  * zero, the contained object is deleted, meaning  you don't need to remember
41  * to delete the object.
42  *
43  * RefPtr<> can store any class that has reference() and unreference() methods.
44  * In gtkmm, that is anything derived from Glib::ObjectBase, such as
45  * Gdk::Pixmap.
46  *
47  * See the "Memory Management" section in the "Programming with gtkmm"
48  * book for further information.
49  */
50 template <class T_CppObject>
51 class RefPtr
52 {
53 public:
54   /** Default constructor
55    *
56    * Afterwards it will be null and use of -> will cause a segmentation fault.
57    */
58   inline RefPtr();
59   
60   /// Destructor - decrements reference count.
61   inline ~RefPtr();
62
63   /// For use only by the ::create() methods.
64   explicit inline RefPtr(T_CppObject* pCppObject);
65
66   /** Copy constructor
67    *
68    * This increments the shared reference count.
69    */
70   inline RefPtr(const RefPtr<T_CppObject>& src);
71
72   /** Copy constructor (from different, but castable type).
73    *
74    * Increments the reference count.
75    */
76   template <class T_CastFrom>
77   inline RefPtr(const RefPtr<T_CastFrom>& src);
78
79   /** Swap the contents of two RefPtr<>.
80    * This method swaps the internal pointers to T_CppObject.  This can be
81    * done safely without involving a reference/unreference cycle and is
82    * therefore highly efficient.
83    */
84   inline void swap(RefPtr<T_CppObject>& other);
85
86   /// Copy from another RefPtr:
87   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CppObject>& src);
88
89   /** Copy from different, but castable type).
90    *
91    * Increments the reference count.
92    */
93   template <class T_CastFrom>
94   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CastFrom>& src);
95
96   /// Tests whether the RefPtr<> point to the same underlying instance.
97   inline bool operator==(const RefPtr<T_CppObject>& src) const;
98   
99   /// See operator==().
100   inline bool operator!=(const RefPtr<T_CppObject>& src) const;
101
102   /** Dereferencing.
103    *
104    * Use the methods of the underlying instance like so:
105    * <code>refptr->memberfun()</code>.
106    */
107   inline T_CppObject* operator->() const;
108
109   /** Test whether the RefPtr<> points to any underlying instance.
110    *
111    * Mimics usage of ordinary pointers:
112    * @code
113    *   if (ptr)
114    *     do_something();
115    * @endcode
116    */
117   inline operator bool() const;
118
119   /// Set underlying instance to 0, decrementing reference count of existing instance appropriately.
120   inline void clear();
121
122
123   /** Dynamic cast to derived class.
124    *
125    * The RefPtr can't be cast with the usual notation so instead you can use
126    * @code
127    *   ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base);
128    * @endcode
129    */
130   template <class T_CastFrom>
131   static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src);
132
133   /** Static cast to derived class.
134    *
135    * Like the dynamic cast; the notation is 
136    * @code
137    *   ptr_derived = RefPtr<Derived>::cast_static(ptr_base);
138    * @endcode
139    */
140   template <class T_CastFrom>
141   static inline RefPtr<T_CppObject> cast_static(const RefPtr<T_CastFrom>& src);
142
143   /** Cast to non-const.
144    *
145    * The RefPtr can't be cast with the usual notation so instead you can use
146    * @code
147    *   ptr_unconst = RefPtr<UnConstType>::cast_const(ptr_const);
148    * @endcode
149    */
150   template <class T_CastFrom>
151   static inline RefPtr<T_CppObject> cast_const(const RefPtr<T_CastFrom>& src);
152
153 private:
154   T_CppObject* pCppObject_;
155 };
156
157
158 #ifndef DOXYGEN_SHOULD_SKIP_THIS
159
160 // RefPtr<>::operator->() comes first here since it's used by other methods.
161 // If it would come after them it wouldn't be inlined.
162
163 template <class T_CppObject> inline
164 T_CppObject* RefPtr<T_CppObject>::operator->() const
165 {
166   return pCppObject_;
167 }
168
169 template <class T_CppObject> inline
170 RefPtr<T_CppObject>::RefPtr()
171 :
172   pCppObject_ (0)
173 {}
174
175 template <class T_CppObject> inline
176 RefPtr<T_CppObject>::~RefPtr()
177 {
178   if(pCppObject_)
179     pCppObject_->unreference(); // This could cause pCppObject to be deleted.
180 }
181
182 template <class T_CppObject> inline
183 RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject)
184 :
185   pCppObject_ (pCppObject)
186 {}
187
188 template <class T_CppObject> inline
189 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src)
190 :
191   pCppObject_ (src.pCppObject_)
192 {
193   if(pCppObject_)
194     pCppObject_->reference();
195 }
196
197 // The templated ctor allows copy construction from any object that's
198 // castable.  Thus, it does downcasts:
199 //   base_ref = derived_ref
200 template <class T_CppObject>
201   template <class T_CastFrom>
202 inline
203 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src)
204 :
205   // A different RefPtr<> will not allow us access to pCppObject_.  We need
206   // to add a get_underlying() for this, but that would encourage incorrect
207   // use, so we use the less well-known operator->() accessor:
208   pCppObject_ (src.operator->())
209 {
210   if(pCppObject_)
211     pCppObject_->reference();
212 }
213
214 template <class T_CppObject> inline
215 void RefPtr<T_CppObject>::swap(RefPtr<T_CppObject>& other)
216 {
217   T_CppObject *const temp = pCppObject_;
218   pCppObject_ = other.pCppObject_;
219   other.pCppObject_ = temp;
220 }
221
222 template <class T_CppObject> inline
223 RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CppObject>& src)
224 {
225   // In case you haven't seen the swap() technique to implement copy
226   // assignment before, here's what it does:
227   //
228   // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
229   //    increasing the reference count of the source object.
230   //
231   // 2) Swap the internal object pointers of *this and the temporary
232   //    RefPtr<>.  After this step, *this already contains the new pointer,
233   //    and the old pointer is now managed by temp.
234   //
235   // 3) The destructor of temp is executed, thereby unreferencing the
236   //    old object pointer.
237   //
238   // This technique is described in Herb Sutter's "Exceptional C++", and
239   // has a number of advantages over conventional approaches:
240   //
241   // - Code reuse by calling the copy ctor.
242   // - Strong exception safety for free.
243   // - Self assignment is handled implicitely.
244   // - Simplicity.
245   // - It just works and is hard to get wrong; i.e. you can use it without
246   //   even thinking about it to implement copy assignment whereever the
247   //   object data is managed indirectly via a pointer, which is very common.
248
249   RefPtr<T_CppObject> temp (src);
250   this->swap(temp);
251   return *this;
252 }
253
254 template <class T_CppObject>
255   template <class T_CastFrom>
256 inline
257 RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
258 {
259   RefPtr<T_CppObject> temp (src);
260   this->swap(temp);
261   return *this;
262 }
263
264 template <class T_CppObject> inline
265 bool RefPtr<T_CppObject>::operator==(const RefPtr<T_CppObject>& src) const
266 {
267   return (pCppObject_ == src.pCppObject_);
268 }
269
270 template <class T_CppObject> inline
271 bool RefPtr<T_CppObject>::operator!=(const RefPtr<T_CppObject>& src) const
272 {
273   return (pCppObject_ != src.pCppObject_);
274 }
275
276 template <class T_CppObject> inline
277 RefPtr<T_CppObject>::operator bool() const
278 {
279   return (pCppObject_ != 0);
280 }
281
282 template <class T_CppObject> inline
283 void RefPtr<T_CppObject>::clear()
284 {
285   RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
286   this->swap(temp);
287 }
288
289 template <class T_CppObject>
290   template <class T_CastFrom>
291 inline
292 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src)
293 {
294   T_CppObject *const pCppObject = dynamic_cast<T_CppObject*>(src.operator->());
295
296   if(pCppObject)
297     pCppObject->reference();
298
299   return RefPtr<T_CppObject>(pCppObject);
300 }
301
302 template <class T_CppObject>
303   template <class T_CastFrom>
304 inline
305 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src)
306 {
307   T_CppObject *const pCppObject = static_cast<T_CppObject*>(src.operator->());
308
309   if(pCppObject)
310     pCppObject->reference();
311
312   return RefPtr<T_CppObject>(pCppObject);
313 }
314
315 template <class T_CppObject>
316   template <class T_CastFrom>
317 inline
318 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_const(const RefPtr<T_CastFrom>& src)
319 {
320   T_CppObject *const pCppObject = const_cast<T_CppObject*>(src.operator->());
321
322   if(pCppObject)
323     pCppObject->reference();
324
325   return RefPtr<T_CppObject>(pCppObject);
326 }
327
328 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
329
330 /** @relates Glib::RefPtr */
331 template <class T_CppObject> inline
332 void swap(RefPtr<T_CppObject>& lhs, RefPtr<T_CppObject>& rhs)
333 {
334   lhs.swap(rhs);
335 }
336
337 } // namespace Glib
338
339
340 #endif /* _GLIBMM_REFPTR_H */
341