Bytemaster's Boost Libraries
|
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