Lunchbox  1.8.0
refPtr.h
1 
2 /* Copyright (c) 2005-2012, Stefan Eilemann <eile@equalizergraphics.com>
3  * 2012-2013, Daniel Nachbaur <danielnachbaur@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU Lesser General Public License version 2.1q as published
7  * by the Free Software Foundation.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #ifndef LUNCHBOX_REFPTR_H
20 #define LUNCHBOX_REFPTR_H
21 
22 #include <lunchbox/debug.h>
23 
24 #include <iostream>
25 #include <stdlib.h>
26 
27 namespace lunchbox
28 {
34  template< class T > class RefPtr
35  {
36  typedef T* RefPtr::*bool_t;
37 
38  public:
40  RefPtr() : _ptr( 0 ) {}
41 
43  RefPtr( T* const ptr ) : _ptr( ptr ) { _ref(); }
44 
46  RefPtr( const RefPtr& from ) : _ptr( from._ptr ) { _ref(); }
47 
52  template< class O > RefPtr( RefPtr< O > from )
53  : _ptr( from.get( )) { _ref(); }
54 
56  ~RefPtr() { _unref(); _ptr = 0; }
57 
59  RefPtr& operator = ( const RefPtr& rhs )
60  {
61  if( _ptr == rhs._ptr )
62  return *this;
63 
64  T* tmp = _ptr;
65  _ptr = rhs._ptr;
66  _ref();
67  if( tmp ) tmp->unref( this );
68  return *this;
69  }
70 
72  RefPtr& operator = ( T* ptr )
73  {
74  if( _ptr == ptr )
75  return *this;
76 
77  T* tmp = _ptr;
78  _ptr = ptr;
79  _ref();
80  if( tmp ) tmp->unref( this );
81  return *this;
82  }
83 
88  bool operator == ( const RefPtr& rhs ) const
89  { return ( _ptr == rhs._ptr ); }
90 
95  bool operator != ( const RefPtr& rhs ) const
96  { return ( _ptr != rhs._ptr ); }
97 
102  operator bool_t() const { return _ptr == 0 ? 0 : &RefPtr::_ptr; }
103 
108  bool operator < ( const RefPtr& rhs ) const
109  { return ( _ptr < rhs._ptr ); }
110 
115  bool operator > ( const RefPtr& rhs ) const
116  { return ( _ptr > rhs._ptr ); }
117 
119  bool operator ! () const { return ( _ptr==0 ); }
120 
125  bool operator == ( const T* ptr ) const { return ( _ptr == ptr ); }
126 
131  bool operator != ( const T* ptr ) const { return ( _ptr != ptr ); }
132 
135  { LBASSERTINFO( _ptr, className( this )); return _ptr; }
137  const T* operator->() const
138  { LBASSERTINFO( _ptr, className( this )); return _ptr; }
141  { LBASSERTINFO( _ptr, className( this )); return *_ptr; }
143  const T& operator*() const
144  { LBASSERTINFO( _ptr, className( this )); return *_ptr; }
145 
147  T* get() { return _ptr; }
149  const T* get() const { return _ptr; }
150 
152  bool isValid() const { return ( _ptr != 0 ); }
153 
154  private:
155  T* _ptr;
156 
158  void _ref() { if(_ptr) _ptr->ref( this ); }
159 
161  void _unref()
162  {
163  if(_ptr)
164  {
165 #ifdef NDEBUG
166  _ptr->unref( this );
167 #else
168  if( _ptr->unref( this ))
169  _ptr = 0;
170 #endif
171  }
172  }
173  };
174 
176  template< class T >
177  inline std::ostream& operator << ( std::ostream& os, RefPtr< T > rp )
178  {
179  const T* p = rp.get();
180  if( !p )
181  return os << "RP[ 0:NULL ]";
182 
183  os << disableFlush << "RP[" << p->getRefCount() << ":" << *p << "]";
184  p->printHolders( os );
185  return os << enableFlush;
186  }
187 
188  template< class T > inline std::string className( const RefPtr<T>& rp )
189  { return className( rp.get( )); }
190 }
191 
192 #include <boost/serialization/split_free.hpp>
193 
194 namespace boost
195 {
196 namespace serialization
197 {
198 
199 template< class Archive, class T >
200 inline void save( Archive& ar, const lunchbox::RefPtr< T >& t,
201  const unsigned int /*version*/ )
202 {
203  const T* ptr = t.get();
204  ar << ptr;
205 }
206 
207 template< class Archive, class T >
208 inline void load( Archive& ar, lunchbox::RefPtr< T >& t,
209  const unsigned int /*version*/ )
210 {
211  T* obj;
212  ar >> obj;
213  t = obj;
214 }
215 
216 template< class Archive, class T >
217 inline void serialize( Archive& ar, lunchbox::RefPtr< T >& t,
218  const unsigned int version )
219 {
220  boost::serialization::split_free( ar, t, version );
221 }
222 
223 }
224 }
225 
226 #endif //LUNCHBOX_REFPTR_H