Line data Source code
1 : #ifndef OPENDDS_DCPS_RCOBJECT_H 2 : #define OPENDDS_DCPS_RCOBJECT_H 3 : 4 : #if !defined (ACE_LACKS_PRAGMA_ONCE) 5 : # pragma once 6 : #endif /* ACE_LACKS_PRAGMA_ONCE */ 7 : 8 : 9 : #include "dds/Versioned_Namespace.h" 10 : 11 : #include "dcps_export.h" 12 : #include "Atomic.h" 13 : #include "PoolAllocationBase.h" 14 : #include "RcHandle_T.h" 15 : 16 : #include <ace/Guard_T.h> 17 : #include <ace/Synch_Traits.h> 18 : 19 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL 20 : 21 : namespace OpenDDS { 22 : namespace DCPS { 23 : 24 : class RcObject; 25 : 26 : class OpenDDS_Dcps_Export WeakObject : public PoolAllocationBase 27 : { 28 : public: 29 : 30 2540 : WeakObject(RcObject* ptr) 31 5080 : : ptr_(ptr) 32 2540 : , ref_count_(1) 33 : { 34 2540 : } 35 : 36 367 : void _add_ref() 37 : { 38 367 : ACE_Guard<ACE_SYNCH_MUTEX> guard(mx_); 39 367 : ++ref_count_; 40 367 : } 41 : 42 2907 : void _remove_ref() 43 : { 44 2907 : ACE_Guard<ACE_SYNCH_MUTEX> guard(mx_); 45 2907 : const long new_count = --ref_count_; 46 2907 : if (new_count == 0) { 47 2540 : guard.release(); 48 2540 : delete this; 49 : } 50 2907 : } 51 : 52 : RcObject* lock(); 53 : bool check_expire(Atomic<long>& count); 54 : 55 : private: 56 : mutable ACE_SYNCH_MUTEX mx_; 57 : RcObject* ptr_; 58 : long ref_count_; 59 : }; 60 : 61 : class OpenDDS_Dcps_Export RcObject : public PoolAllocationBase { 62 : public: 63 : 64 2540 : virtual ~RcObject() 65 2540 : { 66 2540 : weak_object_->_remove_ref(); 67 2540 : } 68 : 69 15790 : virtual void _add_ref() 70 : { 71 15790 : ++ref_count_; 72 15790 : } 73 : 74 17612 : virtual void _remove_ref() 75 : { 76 17612 : if (weak_object_->check_expire(ref_count_)) { 77 1822 : delete this; 78 : } 79 17612 : } 80 : 81 2094 : long ref_count() const 82 : { 83 2094 : return ref_count_; 84 : } 85 : 86 222 : WeakObject* _get_weak_object() const 87 : { 88 222 : weak_object_->_add_ref(); 89 222 : return weak_object_; 90 : } 91 : 92 : protected: 93 2540 : RcObject() 94 2540 : : ref_count_(1) 95 2540 : , weak_object_(new WeakObject(this)) 96 2540 : {} 97 : 98 : private: 99 : Atomic<long> ref_count_; 100 : WeakObject* weak_object_; 101 : 102 : RcObject(const RcObject&); 103 : RcObject& operator=(const RcObject&); 104 : }; 105 : 106 2141 : inline RcObject* WeakObject::lock() 107 : { 108 2141 : ACE_Guard<ACE_SYNCH_MUTEX> guard(mx_); 109 2141 : if (ptr_) { 110 2138 : ptr_->_add_ref(); 111 : } 112 2141 : return ptr_; 113 2141 : } 114 : 115 17612 : inline bool WeakObject::check_expire(Atomic<long>& count) 116 : { 117 17612 : ACE_Guard<ACE_SYNCH_MUTEX> guard(mx_); 118 17612 : const long new_count = --count; 119 17612 : if (new_count == 0 && ptr_) { 120 1822 : ptr_ = 0; 121 1822 : return true; 122 : } 123 15790 : return false; 124 17612 : } 125 : 126 : template <typename T> 127 : class WeakRcHandle 128 : { 129 : public: 130 17 : WeakRcHandle() 131 17 : : weak_object_(0) 132 17 : , cached_(0) 133 : { 134 17 : } 135 : 136 34 : WeakRcHandle(const T& obj) 137 34 : : weak_object_(obj._get_weak_object()) 138 34 : , cached_(const_cast<T*>(&obj)) 139 : { 140 34 : } 141 : 142 217 : WeakRcHandle(const RcHandle<T>& rch) 143 217 : : weak_object_(rch.in() ? rch.in()->_get_weak_object() : 0) 144 217 : , cached_(rch.in()) 145 : { 146 217 : } 147 : 148 145 : WeakRcHandle(const WeakRcHandle& other) 149 145 : : weak_object_(other.weak_object_) 150 145 : , cached_(other.cached_) 151 : { 152 145 : if (weak_object_) { 153 145 : weak_object_->_add_ref(); 154 : } 155 145 : } 156 : 157 413 : ~WeakRcHandle() 158 : { 159 413 : if (weak_object_) { 160 366 : weak_object_->_remove_ref(); 161 : } 162 413 : } 163 : 164 1 : WeakRcHandle& operator=(const WeakRcHandle& other) 165 : { 166 1 : WeakRcHandle tmp(other); 167 1 : std::swap(weak_object_, tmp.weak_object_); 168 1 : std::swap(cached_, tmp.cached_); 169 1 : return *this; 170 1 : } 171 : 172 3 : WeakRcHandle& operator=(const RcHandle<T>& other) 173 : { 174 3 : WeakRcHandle tmp(other); 175 3 : std::swap(weak_object_, tmp.weak_object_); 176 3 : std::swap(cached_, tmp.cached_); 177 3 : return *this; 178 3 : } 179 : 180 1 : WeakRcHandle& operator=(const T& obj) 181 : { 182 1 : WeakRcHandle tmp(obj); 183 1 : std::swap(weak_object_, tmp.weak_object_); 184 1 : std::swap(cached_, tmp.cached_); 185 1 : return *this; 186 1 : } 187 : 188 2193 : RcHandle<T> lock() const 189 : { 190 2193 : if (weak_object_ && weak_object_->lock()) { 191 2138 : return RcHandle<T>(cached_, keep_count()); 192 : } 193 55 : return RcHandle<T>(); 194 : } 195 : 196 3 : bool operator==(const WeakRcHandle& rhs) const 197 : { 198 3 : return weak_object_ == rhs.weak_object_; 199 : } 200 : 201 1 : bool operator!=(const WeakRcHandle& rhs) const 202 : { 203 1 : return weak_object_ != rhs.weak_object_; 204 : } 205 : 206 125 : bool operator<(const WeakRcHandle& rhs) const 207 : { 208 125 : return weak_object_ < rhs.weak_object_; 209 : } 210 : 211 7 : operator bool() const 212 : { 213 7 : return weak_object_; 214 : } 215 : 216 1 : void reset() 217 : { 218 1 : if (weak_object_) { 219 1 : weak_object_->_remove_ref(); 220 1 : weak_object_ = 0; 221 : } 222 1 : cached_ = 0; 223 1 : } 224 : 225 : private: 226 : 227 : WeakRcHandle(WeakObject* obj) 228 : : weak_object_(obj) 229 : , cached_(dynamic_cast<T*>(obj)) 230 : { 231 : } 232 : 233 : WeakObject* weak_object_; 234 : T* cached_; 235 : }; 236 : 237 : } // DCPS 238 : } // OPENDDS 239 : 240 : OPENDDS_END_VERSIONED_NAMESPACE_DECL 241 : 242 : #endif /* end of include guard: OPENDDS_DCPS_RCOBJECT_H */