1 /* 2 * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _WEAK_REFERENCEABLE_H 6 #define _WEAK_REFERENCEABLE_H 7 8 9 #include <Referenceable.h> 10 11 #include <new> 12 13 14 namespace BPrivate { 15 16 17 class BWeakReferenceable; 18 19 20 class WeakPointer : public BReferenceable { 21 public: 22 WeakPointer(BWeakReferenceable* object); 23 ~WeakPointer(); 24 25 BWeakReferenceable* Get(); 26 bool Put(); 27 28 int32 UseCount() const; 29 30 void GetUnchecked(); 31 32 private: 33 int32 fUseCount; 34 BWeakReferenceable* fObject; 35 }; 36 37 38 class BWeakReferenceable { 39 public: 40 BWeakReferenceable(); 41 virtual ~BWeakReferenceable(); 42 43 status_t InitCheck(); 44 45 void AcquireReference() 46 { fPointer->GetUnchecked(); } 47 48 bool ReleaseReference() 49 { return fPointer->Put(); } 50 51 int32 CountReferences() const 52 { return fPointer->UseCount(); } 53 54 WeakPointer* GetWeakPointer(); 55 private: 56 WeakPointer* fPointer; 57 }; 58 59 60 template<typename Type> 61 class BWeakReference { 62 public: 63 BWeakReference() 64 : 65 fPointer(NULL) 66 { 67 } 68 69 BWeakReference(Type* object) 70 : 71 fPointer(NULL) 72 { 73 SetTo(object); 74 } 75 76 BWeakReference(const BWeakReference<Type>& other) 77 : 78 fPointer(NULL) 79 { 80 SetTo(other); 81 } 82 83 BWeakReference(const BReference<Type>& other) 84 : 85 fPointer(NULL) 86 { 87 SetTo(other); 88 } 89 90 template<typename OtherType> 91 BWeakReference(const BReference<OtherType>& other) 92 : 93 fPointer(NULL) 94 { 95 SetTo(other.Get()); 96 } 97 98 template<typename OtherType> 99 BWeakReference(const BWeakReference<OtherType>& other) 100 : 101 fPointer(NULL) 102 { 103 SetTo(other); 104 } 105 106 ~BWeakReference() 107 { 108 Unset(); 109 } 110 111 void SetTo(Type* object) 112 { 113 Unset(); 114 115 if (object != NULL) 116 fPointer = object->GetWeakPointer(); 117 } 118 119 void SetTo(const BWeakReference<Type>& other) 120 { 121 Unset(); 122 123 if (other.fPointer) { 124 fPointer = other.fPointer; 125 fPointer->AcquireReference(); 126 } 127 } 128 129 template<typename OtherType> 130 void SetTo(const BWeakReference<OtherType>& other) 131 { 132 // Just a compiler check if the types are compatible. 133 OtherType* otherDummy = NULL; 134 Type* dummy = otherDummy; 135 dummy = NULL; 136 137 Unset(); 138 139 if (other.PrivatePointer()) { 140 fPointer = const_cast<WeakPointer*>(other.PrivatePointer()); 141 fPointer->AcquireReference(); 142 } 143 } 144 145 void SetTo(const BReference<Type>& other) 146 { 147 SetTo(other.Get()); 148 } 149 150 void Unset() 151 { 152 if (fPointer != NULL) { 153 fPointer->ReleaseReference(); 154 fPointer = NULL; 155 } 156 } 157 158 bool IsAlive() 159 { 160 if (fPointer == NULL) 161 return false; 162 Type* object = static_cast<Type*>(fPointer->Get()); 163 if (object == NULL) 164 return false; 165 fPointer->Put(); 166 return true; 167 } 168 169 BReference<Type> GetReference() 170 { 171 Type* object = static_cast<Type*>(fPointer->Get()); 172 return BReference<Type>(object, true); 173 } 174 175 BWeakReference& operator=(const BWeakReference<Type>& other) 176 { 177 if (this == &other) 178 return *this; 179 180 SetTo(other); 181 return *this; 182 } 183 184 BWeakReference& operator=(Type* other) 185 { 186 SetTo(other); 187 return *this; 188 } 189 190 BWeakReference& operator=(const BReference<Type>& other) 191 { 192 SetTo(other.Get()); 193 return *this; 194 } 195 196 template<typename OtherType> 197 BWeakReference& operator=(const BReference<OtherType>& other) 198 { 199 SetTo(other.Get()); 200 return *this; 201 } 202 203 template<typename OtherType> 204 BWeakReference& operator=(const BWeakReference<OtherType>& other) 205 { 206 SetTo(other); 207 return *this; 208 } 209 210 bool operator==(const BWeakReference<Type>& other) const 211 { 212 return fPointer == other.fPointer; 213 } 214 215 bool operator!=(const BWeakReference<Type>& other) const 216 { 217 return fPointer != other.fPointer; 218 } 219 220 /*! Do not use this if you do not know what you are doing. The WeakPointer 221 is for internal use only. 222 */ 223 const WeakPointer* PrivatePointer() const 224 { 225 return fPointer; 226 } 227 228 private: 229 WeakPointer* fPointer; 230 }; 231 232 233 // #pragma mark - 234 235 236 inline 237 WeakPointer::WeakPointer(BWeakReferenceable* object) 238 : 239 fUseCount(1), 240 fObject(object) 241 { 242 } 243 244 245 inline 246 WeakPointer::~WeakPointer() 247 { 248 } 249 250 251 inline BWeakReferenceable* 252 WeakPointer::Get() 253 { 254 int32 count = -11; 255 256 do { 257 count = atomic_get(&fUseCount); 258 if (count == 0) 259 return NULL; 260 } while (atomic_test_and_set(&fUseCount, count + 1, count) != count); 261 262 return fObject; 263 } 264 265 266 inline bool 267 WeakPointer::Put() 268 { 269 if (atomic_add(&fUseCount, -1) == 1) { 270 delete fObject; 271 return true; 272 } 273 274 return false; 275 } 276 277 278 inline int32 279 WeakPointer::UseCount() const 280 { 281 return fUseCount; 282 } 283 284 285 inline void 286 WeakPointer::GetUnchecked() 287 { 288 atomic_add(&fUseCount, 1); 289 } 290 291 292 // #pragma - 293 294 295 inline 296 BWeakReferenceable::BWeakReferenceable() 297 : 298 fPointer(new(std::nothrow) WeakPointer(this)) 299 { 300 } 301 302 303 inline 304 BWeakReferenceable::~BWeakReferenceable() 305 { 306 fPointer->ReleaseReference(); 307 } 308 309 310 inline status_t 311 BWeakReferenceable::InitCheck() 312 { 313 if (fPointer == NULL) 314 return B_NO_MEMORY; 315 return B_OK; 316 } 317 318 319 inline WeakPointer* 320 BWeakReferenceable::GetWeakPointer() 321 { 322 fPointer->AcquireReference(); 323 return fPointer; 324 } 325 326 } // namespace BPrivate 327 328 using BPrivate::BWeakReferenceable; 329 using BPrivate::BWeakReference; 330 331 #endif // _WEAK_REFERENCEABLE_H 332