2008-06-02 17:41:35 -04:00
// -*- c++ -*-
# ifndef _GLIBMM_REFPTR_H
# define _GLIBMM_REFPTR_H
2009-07-02 12:00:45 -04:00
/* $Id: refptr.h 476 2007-12-28 11:11:42Z murrayc $ */
2008-06-02 17:41:35 -04:00
/* Copyright 2002 The gtkmm Development Team
*
* This library is free software ; you can redistribute it and / or
2009-07-02 12:00:45 -04:00
* modify it under the terms of the GNU Library General Public
2008-06-02 17:41:35 -04:00
* License as published by the Free Software Foundation ; either
2009-07-02 12:00:45 -04:00
* version 2 of the License , or ( at your option ) any later version .
2008-06-02 17:41:35 -04:00
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
2009-07-02 12:00:45 -04:00
* Library General Public License for more details .
2008-06-02 17:41:35 -04:00
*
2009-07-02 12:00:45 -04:00
* You should have received a copy of the GNU Library General Public
2008-06-02 17:41:35 -04:00
* License along with this library ; if not , write to the Free
* Software Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
namespace Glib
{
/** RefPtr<> is a reference-counting shared smartpointer.
*
* Some objects in gtkmm are obtained from a shared
* store . Consequently you cannot instantiate them yourself . Instead they
* return a RefPtr which behaves much like an ordinary pointer in that members
* can be reached with the usual < code > object_ptr - > member < / code > notation .
* Unlike most other smart pointers , RefPtr doesn ' t support dereferencing
* through < code > * object_ptr < / code > .
*
* Reference counting means that a shared reference count is incremented each
* time a RefPtr is copied , and decremented each time a RefPtr is destroyed ,
* for instance when it leaves its scope . When the reference count reaches
* zero , the contained object is deleted , meaning you don ' t need to remember
* to delete the object .
*
* RefPtr < > can store any class that has reference ( ) and unreference ( ) methods .
* In gtkmm , that is anything derived from Glib : : ObjectBase , such as
* Gdk : : Pixmap .
*
* See the " Memory Management " section in the " Programming with gtkmm "
* book for further information .
*/
template < class T_CppObject >
class RefPtr
{
public :
/** Default constructor
*
* Afterwards it will be null and use of - > will cause a segmentation fault .
*/
inline RefPtr ( ) ;
/// Destructor - decrements reference count.
inline ~ RefPtr ( ) ;
/// For use only by the ::create() methods.
explicit inline RefPtr ( T_CppObject * pCppObject ) ;
/** Copy constructor
*
* This increments the shared reference count .
*/
inline RefPtr ( const RefPtr < T_CppObject > & src ) ;
/** Copy constructor (from different, but castable type).
*
* Increments the reference count .
*/
template < class T_CastFrom >
inline RefPtr ( const RefPtr < T_CastFrom > & src ) ;
/** Swap the contents of two RefPtr<>.
* This method swaps the internal pointers to T_CppObject . This can be
* done safely without involving a reference / unreference cycle and is
* therefore highly efficient .
*/
inline void swap ( RefPtr < T_CppObject > & other ) ;
/// Copy from another RefPtr:
inline RefPtr < T_CppObject > & operator = ( const RefPtr < T_CppObject > & src ) ;
/** Copy from different, but castable type).
*
* Increments the reference count .
*/
template < class T_CastFrom >
inline RefPtr < T_CppObject > & operator = ( const RefPtr < T_CastFrom > & src ) ;
/// Tests whether the RefPtr<> point to the same underlying instance.
inline bool operator = = ( const RefPtr < T_CppObject > & src ) const ;
/// See operator==().
inline bool operator ! = ( const RefPtr < T_CppObject > & src ) const ;
/** Dereferencing.
*
* Use the methods of the underlying instance like so :
* < code > refptr - > memberfun ( ) < / code > .
*/
inline T_CppObject * operator - > ( ) const ;
/** Test whether the RefPtr<> points to any underlying instance.
*
* Mimics usage of ordinary pointers :
* @ code
* if ( ptr )
* do_something ( ) ;
* @ endcode
*/
inline operator bool ( ) const ;
2009-07-02 09:12:38 -04:00
# ifndef GLIBMM_DISABLE_DEPRECATED
/// @deprecated Use reset() instead because this leads to confusion with clear() methods on the underlying class. For instance, people use .clear() when they mean ->clear().
2008-06-02 17:41:35 -04:00
inline void clear ( ) ;
2009-07-02 09:12:38 -04:00
# endif //GLIBMM_DISABLE_DEPRECATED
2008-06-02 17:41:35 -04:00
2009-07-02 09:12:38 -04:00
/** Set underlying instance to 0, decrementing reference count of existing instance appropriately.
* @ newin2p16
*/
inline void reset ( ) ;
2008-06-02 17:41:35 -04:00
/** Dynamic cast to derived class.
*
* The RefPtr can ' t be cast with the usual notation so instead you can use
* @ code
* ptr_derived = RefPtr < Derived > : : cast_dynamic ( ptr_base ) ;
* @ endcode
*/
template < class T_CastFrom >
static inline RefPtr < T_CppObject > cast_dynamic ( const RefPtr < T_CastFrom > & src ) ;
/** Static cast to derived class.
*
* Like the dynamic cast ; the notation is
* @ code
* ptr_derived = RefPtr < Derived > : : cast_static ( ptr_base ) ;
* @ endcode
*/
template < class T_CastFrom >
static inline RefPtr < T_CppObject > cast_static ( const RefPtr < T_CastFrom > & src ) ;
/** Cast to non-const.
*
* The RefPtr can ' t be cast with the usual notation so instead you can use
* @ code
* ptr_unconst = RefPtr < UnConstType > : : cast_const ( ptr_const ) ;
* @ endcode
*/
template < class T_CastFrom >
static inline RefPtr < T_CppObject > cast_const ( const RefPtr < T_CastFrom > & src ) ;
private :
T_CppObject * pCppObject_ ;
} ;
# ifndef DOXYGEN_SHOULD_SKIP_THIS
// RefPtr<>::operator->() comes first here since it's used by other methods.
// If it would come after them it wouldn't be inlined.
template < class T_CppObject > inline
T_CppObject * RefPtr < T_CppObject > : : operator - > ( ) const
{
return pCppObject_ ;
}
template < class T_CppObject > inline
RefPtr < T_CppObject > : : RefPtr ( )
:
pCppObject_ ( 0 )
{ }
template < class T_CppObject > inline
RefPtr < T_CppObject > : : ~ RefPtr ( )
{
if ( pCppObject_ )
pCppObject_ - > unreference ( ) ; // This could cause pCppObject to be deleted.
}
template < class T_CppObject > inline
RefPtr < T_CppObject > : : RefPtr ( T_CppObject * pCppObject )
:
pCppObject_ ( pCppObject )
{ }
template < class T_CppObject > inline
RefPtr < T_CppObject > : : RefPtr ( const RefPtr < T_CppObject > & src )
:
pCppObject_ ( src . pCppObject_ )
{
if ( pCppObject_ )
pCppObject_ - > reference ( ) ;
}
// The templated ctor allows copy construction from any object that's
// castable. Thus, it does downcasts:
// base_ref = derived_ref
template < class T_CppObject >
template < class T_CastFrom >
inline
RefPtr < T_CppObject > : : RefPtr ( const RefPtr < T_CastFrom > & src )
:
// A different RefPtr<> will not allow us access to pCppObject_. We need
// to add a get_underlying() for this, but that would encourage incorrect
// use, so we use the less well-known operator->() accessor:
pCppObject_ ( src . operator - > ( ) )
{
if ( pCppObject_ )
pCppObject_ - > reference ( ) ;
}
template < class T_CppObject > inline
void RefPtr < T_CppObject > : : swap ( RefPtr < T_CppObject > & other )
{
T_CppObject * const temp = pCppObject_ ;
pCppObject_ = other . pCppObject_ ;
other . pCppObject_ = temp ;
}
template < class T_CppObject > inline
RefPtr < T_CppObject > & RefPtr < T_CppObject > : : operator = ( const RefPtr < T_CppObject > & src )
{
// In case you haven't seen the swap() technique to implement copy
// assignment before, here's what it does:
//
// 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
// increasing the reference count of the source object.
//
// 2) Swap the internal object pointers of *this and the temporary
// RefPtr<>. After this step, *this already contains the new pointer,
// and the old pointer is now managed by temp.
//
// 3) The destructor of temp is executed, thereby unreferencing the
// old object pointer.
//
// This technique is described in Herb Sutter's "Exceptional C++", and
// has a number of advantages over conventional approaches:
//
// - Code reuse by calling the copy ctor.
// - Strong exception safety for free.
// - Self assignment is handled implicitely.
// - Simplicity.
// - It just works and is hard to get wrong; i.e. you can use it without
// even thinking about it to implement copy assignment whereever the
// object data is managed indirectly via a pointer, which is very common.
RefPtr < T_CppObject > temp ( src ) ;
this - > swap ( temp ) ;
return * this ;
}
template < class T_CppObject >
template < class T_CastFrom >
inline
RefPtr < T_CppObject > & RefPtr < T_CppObject > : : operator = ( const RefPtr < T_CastFrom > & src )
{
RefPtr < T_CppObject > temp ( src ) ;
this - > swap ( temp ) ;
return * this ;
}
template < class T_CppObject > inline
bool RefPtr < T_CppObject > : : operator = = ( const RefPtr < T_CppObject > & src ) const
{
return ( pCppObject_ = = src . pCppObject_ ) ;
}
template < class T_CppObject > inline
bool RefPtr < T_CppObject > : : operator ! = ( const RefPtr < T_CppObject > & src ) const
{
return ( pCppObject_ ! = src . pCppObject_ ) ;
}
template < class T_CppObject > inline
RefPtr < T_CppObject > : : operator bool ( ) const
{
return ( pCppObject_ ! = 0 ) ;
}
2009-07-02 09:12:38 -04:00
# ifndef GLIBMM_DISABLE_DEPRECATED
2008-06-02 17:41:35 -04:00
template < class T_CppObject > inline
void RefPtr < T_CppObject > : : clear ( )
2009-07-02 09:12:38 -04:00
{
reset ( ) ;
}
# endif //GLIBMM_DISABLE_DEPRECATED
template < class T_CppObject > inline
void RefPtr < T_CppObject > : : reset ( )
2008-06-02 17:41:35 -04:00
{
RefPtr < T_CppObject > temp ; // swap with an empty RefPtr<> to clear *this
this - > swap ( temp ) ;
}
template < class T_CppObject >
template < class T_CastFrom >
inline
RefPtr < T_CppObject > RefPtr < T_CppObject > : : cast_dynamic ( const RefPtr < T_CastFrom > & src )
{
T_CppObject * const pCppObject = dynamic_cast < T_CppObject * > ( src . operator - > ( ) ) ;
if ( pCppObject )
pCppObject - > reference ( ) ;
return RefPtr < T_CppObject > ( pCppObject ) ;
}
template < class T_CppObject >
template < class T_CastFrom >
inline
RefPtr < T_CppObject > RefPtr < T_CppObject > : : cast_static ( const RefPtr < T_CastFrom > & src )
{
T_CppObject * const pCppObject = static_cast < T_CppObject * > ( src . operator - > ( ) ) ;
if ( pCppObject )
pCppObject - > reference ( ) ;
return RefPtr < T_CppObject > ( pCppObject ) ;
}
template < class T_CppObject >
template < class T_CastFrom >
inline
RefPtr < T_CppObject > RefPtr < T_CppObject > : : cast_const ( const RefPtr < T_CastFrom > & src )
{
T_CppObject * const pCppObject = const_cast < T_CppObject * > ( src . operator - > ( ) ) ;
if ( pCppObject )
pCppObject - > reference ( ) ;
return RefPtr < T_CppObject > ( pCppObject ) ;
}
# endif /* DOXYGEN_SHOULD_SKIP_THIS */
/** @relates Glib::RefPtr */
template < class T_CppObject > inline
void swap ( RefPtr < T_CppObject > & lhs , RefPtr < T_CppObject > & rhs )
{
lhs . swap ( rhs ) ;
}
} // namespace Glib
# endif /* _GLIBMM_REFPTR_H */