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