Lunchbox  1.4.0
refPtr.h
00001 
00002 /* Copyright (c) 2005-2012, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1q as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00018 #ifndef LUNCHBOX_REFPTR_H
00019 #define LUNCHBOX_REFPTR_H
00020 
00021 #include <lunchbox/debug.h>
00022 
00023 #include <iostream>
00024 #include <stdlib.h>
00025 
00026 namespace lunchbox
00027 {
00033     template< class T > class RefPtr 
00034     {
00035         typedef T* RefPtr::*bool_t;
00036 
00037     public:
00039         RefPtr()                     : _ptr( 0 )         {}
00040 
00042         RefPtr( T* const ptr )       : _ptr( ptr )       { _ref(); }
00043 
00045         RefPtr( const RefPtr& from ) : _ptr( from._ptr ) { _ref(); }
00046 
00051         template< class O > RefPtr( RefPtr< O > from )
00052                 : _ptr( from.get( )) { _ref(); }
00053 
00055         ~RefPtr() { _unref(); _ptr = 0; }
00056 
00058         RefPtr& operator = ( const RefPtr& rhs )
00059             {
00060                 if( _ptr == rhs._ptr )
00061                     return *this;
00062 
00063                 T* tmp = _ptr;
00064                 _ptr = rhs._ptr;
00065                 _ref();
00066                 if( tmp ) tmp->unref( this );
00067                 return *this;
00068             }
00069 
00071         RefPtr& operator = ( T* ptr )
00072             {
00073                 if( _ptr == ptr )
00074                     return *this;
00075 
00076                 T* tmp = _ptr;
00077                 _ptr = ptr;
00078                 _ref();
00079                 if( tmp ) tmp->unref( this );
00080                 return *this;
00081             }
00082 
00087         bool operator == ( const RefPtr& rhs ) const 
00088             { return ( _ptr == rhs._ptr ); }
00089 
00094         bool operator != ( const RefPtr& rhs ) const
00095             { return ( _ptr != rhs._ptr ); }
00096 
00101         operator bool_t() const { return _ptr == 0 ? 0 : &RefPtr::_ptr; }
00102 
00107         bool operator < ( const RefPtr& rhs ) const
00108             { return ( _ptr < rhs._ptr ); }
00109 
00114         bool operator > ( const RefPtr& rhs ) const
00115             { return ( _ptr > rhs._ptr ); }
00116 
00118         bool operator ! () const               { return ( _ptr==0 ); }
00119 
00124         bool operator == ( const T* ptr ) const { return ( _ptr == ptr ); }
00125 
00130         bool operator != ( const T* ptr ) const { return ( _ptr != ptr ); }
00131 
00133         T*       operator->()       
00134             { LBASSERTINFO( _ptr, className( this )); return _ptr; }
00136         const T* operator->() const
00137             { LBASSERTINFO( _ptr, className( this )); return _ptr; }
00139         T&       operator*()        
00140             { LBASSERTINFO( _ptr, className( this )); return *_ptr; }
00142         const T& operator*() const  
00143             { LBASSERTINFO( _ptr, className( this )); return *_ptr; }
00144 
00146         T*       get()                { return _ptr; }
00148         const T* get() const          { return _ptr; }
00149 
00151         bool isValid() const { return ( _ptr != 0 ); }
00152         
00153     private:
00154         T* _ptr;
00155 
00157         void _ref()   { if(_ptr) _ptr->ref( this ); }
00158 
00160         void _unref() 
00161         {
00162             if(_ptr)
00163             {
00164 #ifndef NDEBUG
00165                 const bool abondon = (_ptr->getRefCount() == 1);
00166                 _ptr->unref( this );
00167                 if( abondon ) 
00168                     _ptr = 0;
00169 #else
00170                 _ptr->unref( this );
00171 #endif
00172             }
00173         }
00174     };
00175 
00177     template< class T >
00178     inline std::ostream& operator << ( std::ostream& os, RefPtr< T > rp )
00179     {
00180         const T* p = rp.get();
00181         if( !p )
00182             return os << "RP[ 0:NULL ]";
00183 
00184         os << disableFlush << "RP[" << p->getRefCount() << ":" << *p << "]";
00185         p->printHolders( os );
00186         return os << enableFlush;
00187     }
00188 
00189     template< class T > inline std::string className( const RefPtr<T>& rp )
00190         { return className( rp.get( )); }
00191 }
00192 
00193 #ifdef LUNCHBOX_USE_BOOST
00194 #  include <boost/serialization/split_free.hpp>
00195 
00196 namespace boost
00197 {
00198 namespace serialization
00199 {
00200 
00201 template< class Archive, class T >
00202 inline void save( Archive& ar, const lunchbox::RefPtr< T >& t,
00203                   const unsigned int /*version*/ )
00204 {
00205     const T* ptr = t.get();
00206     ar << ptr;
00207 }
00208 
00209 template< class Archive, class T >
00210 inline void load( Archive& ar, lunchbox::RefPtr< T >& t,
00211                   const unsigned int /*version*/ )
00212 {
00213     T* obj;
00214     ar >> obj;
00215     t = obj;
00216 }
00217 
00218 template< class Archive, class T >
00219 inline void serialize( Archive& ar, lunchbox::RefPtr< T >& t,
00220                        const unsigned int version )
00221 {
00222     boost::serialization::split_free( ar, t, version );
00223 }
00224 
00225 }
00226 }
00227 
00228 #endif // LUNCHBOX_USE_BOOST
00229 #endif //LUNCHBOX_REFPTR_H