00001 #ifndef RCOBJECT_H_E92AD5BB 00002 #define RCOBJECT_H_E92AD5BB 00003 00004 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00005 # pragma once 00006 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00007 00008 00009 #include "dds/Versioned_Namespace.h" 00010 #include "ace/Atomic_Op.h" 00011 #include "ace/Synch_Traits.h" 00012 #include "dds/DCPS/PoolAllocationBase.h" 00013 #include "RcHandle_T.h" 00014 00015 OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL 00016 00017 namespace OpenDDS { 00018 namespace DCPS { 00019 00020 class RcObject; 00021 00022 class WeakObject : public PoolAllocationBase 00023 { 00024 public: 00025 WeakObject(RcObject* ptr) 00026 : ref_count_(1) 00027 , ptr_(ptr) 00028 , expired_(false) 00029 { 00030 } 00031 00032 void _add_ref() { 00033 ++this->ref_count_; 00034 } 00035 00036 void _remove_ref(){ 00037 const long new_count = --this->ref_count_; 00038 00039 if (new_count == 0) { 00040 delete this; 00041 } 00042 } 00043 00044 RcObject* lock(); 00045 bool set_expire(); 00046 private: 00047 ACE_Atomic_Op<ACE_SYNCH_MUTEX, long> ref_count_; 00048 ACE_SYNCH_MUTEX mx_; 00049 RcObject* const ptr_; 00050 bool expired_; 00051 }; 00052 00053 class RcObject : public PoolAllocationBase { 00054 public: 00055 00056 virtual ~RcObject(){ 00057 weak_object_->_remove_ref(); 00058 } 00059 00060 virtual void _add_ref() { 00061 ++this->ref_count_; 00062 } 00063 00064 virtual void _remove_ref() { 00065 const long new_count = --this->ref_count_; 00066 if (new_count == 0 && weak_object_->set_expire()) { 00067 delete this; 00068 } 00069 } 00070 00071 /// This accessor is purely for debugging purposes 00072 long ref_count() const { 00073 return this->ref_count_.value(); 00074 } 00075 00076 WeakObject* 00077 _get_weak_object() const { 00078 weak_object_->_add_ref(); 00079 return weak_object_; 00080 } 00081 00082 protected: 00083 00084 RcObject() 00085 : ref_count_(1) 00086 , weak_object_( new WeakObject(this) ) 00087 {} 00088 00089 00090 private: 00091 00092 ACE_Atomic_Op<ACE_SYNCH_MUTEX, long> ref_count_; 00093 WeakObject* weak_object_; 00094 00095 RcObject(const RcObject&); 00096 RcObject& operator=(const RcObject&); 00097 }; 00098 00099 00100 inline RcObject* 00101 WeakObject::lock() 00102 { 00103 ACE_Guard<ACE_SYNCH_MUTEX> guard(mx_); 00104 if (! expired_) { 00105 ptr_->_add_ref(); 00106 return ptr_; 00107 } 00108 return 0; 00109 } 00110 00111 inline bool 00112 WeakObject::set_expire() 00113 { 00114 ACE_Guard<ACE_SYNCH_MUTEX> guard(mx_); 00115 if (!expired_ && ptr_->ref_count() == 0) { 00116 expired_ = true; 00117 } 00118 return expired_; 00119 } 00120 00121 template <typename T> 00122 class WeakRcHandle 00123 { 00124 public: 00125 WeakRcHandle() 00126 : weak_object_(0) 00127 { 00128 } 00129 00130 WeakRcHandle(const T& obj) 00131 : weak_object_(obj._get_weak_object()) { 00132 } 00133 00134 WeakRcHandle(const RcHandle<T>& rch) 00135 : weak_object_(rch.in() ? rch.in()->_get_weak_object() : 0) { 00136 } 00137 00138 WeakRcHandle(const WeakRcHandle& other) 00139 : weak_object_(other.weak_object_){ 00140 if (weak_object_) 00141 weak_object_->_add_ref(); 00142 } 00143 00144 ~WeakRcHandle(){ 00145 if (weak_object_) 00146 weak_object_->_remove_ref(); 00147 } 00148 00149 WeakRcHandle& operator = (const WeakRcHandle& other) { 00150 WeakRcHandle tmp(other); 00151 std::swap(weak_object_, tmp.weak_object_); 00152 return *this; 00153 } 00154 00155 WeakRcHandle& operator = (const RcHandle<T>& other) { 00156 WeakRcHandle tmp(other); 00157 std::swap(weak_object_, tmp.weak_object_); 00158 return *this; 00159 } 00160 00161 WeakRcHandle& operator = (const T& obj) { 00162 WeakRcHandle tmp(obj); 00163 std::swap(weak_object_, tmp.weak_object_); 00164 return *this; 00165 } 00166 00167 RcHandle<T> lock() const { 00168 if (weak_object_){ 00169 return RcHandle<T>(dynamic_cast<T*>(weak_object_->lock()), keep_count()); 00170 } 00171 return RcHandle<T>(); 00172 } 00173 00174 bool operator==(const WeakRcHandle& rhs) const 00175 { 00176 return weak_object_ == rhs.weak_object_; 00177 } 00178 00179 bool operator!=(const WeakRcHandle& rhs) const 00180 { 00181 return weak_object_ != rhs.weak_object_; 00182 } 00183 00184 bool operator < (const WeakRcHandle& rhs) const 00185 { 00186 return weak_object_ < rhs.weak_object_; 00187 } 00188 00189 operator bool() const { 00190 return weak_object_; 00191 } 00192 00193 void reset() { 00194 if (weak_object_) { 00195 weak_object_->_remove_ref(); 00196 weak_object_ = 0; 00197 } 00198 } 00199 00200 private: 00201 00202 WeakRcHandle(WeakObject* obj) 00203 : weak_object_(obj) 00204 { 00205 } 00206 00207 WeakObject* weak_object_; 00208 }; 00209 00210 }// DCPS 00211 }// OPENDDS 00212 00213 OPENDDS_END_VERSIONED_NAMESPACE_DECL 00214 00215 #endif /* end of include guard: RCOBJECT_H_E92AD5BB */