Bytemaster's Boost Libraries
/Users/dlarimer/dev/libs/cmt/include/boost/cmt/retainable.hpp
00001 #ifndef _BOOST_CMT_RETAINABLE_HPP_
00002 #define _BOOST_CMT_RETAINABLE_HPP_
00003 #include <boost/assert.hpp>
00004 #include <boost/intrusive_ptr.hpp>
00005 #include <boost/atomic.hpp>
00006 #include <boost/memory_order.hpp>
00007 
00008 namespace boost { namespace cmt {
00009 
00014 template<typename T>
00015 class stack_retainable : public T {
00016     public:
00017         template<typename A, typename B, typename C>
00018         stack_retainable( const A& a, const B& b, const C& c)
00019         :T(a,b,c){}
00020         template<typename A, typename B, typename C, typename D>
00021         stack_retainable( const A& a, const B& b, const C& c, const D& d)
00022         :T(a,b,c,d){}
00023 
00024         stack_retainable(){}
00025         ~stack_retainable() {}
00026 };
00027 
00036 class retainable {
00037     public:
00038         template<typename T>
00039         friend class stack_retainable;
00040 
00041         retainable():m_ref_count(1) {}
00042 
00043         inline void retain() {
00044             m_ref_count.fetch_add(1, boost::memory_order_relaxed);
00045         }
00046 
00047         inline void release() {
00048             if( 1 == m_ref_count.fetch_sub(1, boost::memory_order_release) ) {
00049                 boost::atomic_thread_fence(boost::memory_order_acquire);
00050                 delete this;
00051             }
00052         }
00053 
00054     protected:
00055         virtual ~retainable() {}
00056 
00057     private:
00058         retainable(const retainable&):m_ref_count(1) {}
00059 
00060         retainable& operator=(const retainable& ) {
00061             return *this;
00062         }
00063 
00064         boost::atomic<int32_t>  m_ref_count;
00065 };
00066 
00067 
00068 
00069 
00070 template<typename T>
00071 class retainable_ptr
00072 {
00073     public:
00074         explicit retainable_ptr(T* t = 0, bool inc = false)
00075         :cnt(t) {
00076             if( inc && cnt ) cnt->retain();
00077         }
00078 
00079         retainable_ptr( const retainable_ptr<T>& copy )
00080         :cnt(copy.cnt) {
00081             if( cnt ) cnt->retain();
00082         }
00083 
00084 #ifdef BOOST_HAS_RVALUE_REFS
00085         retainable_ptr( retainable_ptr<T>&& mv )
00086         :cnt(mv.cnt) {
00087             mv.cnt = NULL;
00088         }
00089 
00090         inline retainable_ptr<T>& operator=(retainable_ptr<T>&& mv ) {
00091             cnt = mv.cnt;
00092             mv.cnt = NULL;
00093             return *this;
00094         }
00095 #endif
00096         ~retainable_ptr() {
00097             if( cnt ) cnt->release();
00098         }
00099 
00100         template<typename U>
00101         operator retainable_ptr<U>()const {
00102             retainable_ptr<U> u;
00103             u.cnt = dynamic_cast<U*>(cnt);
00104             if( u.cnt ) 
00105                 u.cnt->retain();
00106             return u;
00107         }
00108         retainable_ptr& reset()  {
00109             if( !cnt ) 
00110                 return *this; 
00111             cnt->release();
00112             cnt = 0; 
00113             return *this; 
00114         }
00115 
00116         inline bool operator!()const { return cnt == 0; }
00117         inline operator bool()const { return cnt != 0; }
00118 
00119         inline retainable_ptr<T>& operator=(const retainable_ptr<T>& copy ) {
00120             if( cnt == copy.cnt ) 
00121                 return *this;
00122             if( cnt ) 
00123                 cnt->release();
00124             cnt = copy.cnt;
00125             if( cnt ) 
00126                 cnt->retain();
00127             return *this;
00128         }
00129         inline T& operator* () const  { return *cnt; }
00130         inline T * operator-> () const { return cnt; }
00131 
00132         inline bool operator==( const retainable_ptr& p )const {
00133             return get() == p.get();
00134         }
00135         inline bool operator<( const retainable_ptr& p )const {
00136             return get() < p.get();
00137         }
00138         inline T * get() const { return cnt; }
00139 
00140     private:
00141         template<typename U> friend class retainable_ptr;
00142         T* cnt;
00143 };
00144 template<typename T>
00145 T* get_pointer( const retainable_ptr<T>& p ) { return p.get(); }
00146 
00147 template<class T, class U> 
00148 inline bool operator==(retainable_ptr<T> const & a, retainable_ptr<U> const & b) {
00149     return a.get() == b.get();
00150 }
00151 
00152 template<class T, class U> 
00153 inline bool operator!=(retainable_ptr<T> const & a, retainable_ptr<U> const & b) {
00154     return a.get() != b.get();
00155 }
00156 
00157 template<class T, class U> 
00158 inline retainable_ptr<T> dynamic_retainable_cast( const retainable_ptr<U>& u ) {
00159     T* t = dynamic_cast<T*>(u.get());
00160     if( t ) t->retain();
00161     return retainable_ptr<T>( t );
00162 }
00163 template<class T, class U> 
00164 inline retainable_ptr<T> static_retainable_cast( const retainable_ptr<U>& u ) {
00165     T* t = static_cast<T*>(u.get());
00166     if( t )
00167         t->retain();
00168     return retainable_ptr<T>( t );
00169 }
00170 
00171 } } // namespace boost::cmt
00172 
00173 #endif
 All Classes Namespaces Files Functions Variables Typedefs Defines