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 12 namespace BPrivate { 13 14 template<typename Type> class WeakReferenceable; 15 16 template<typename Type> 17 class WeakPointer : public Referenceable { 18 public: 19 Type* Get(); 20 bool Put(); 21 22 int32 UseCount() const; 23 24 private: 25 friend class WeakReferenceable<Type>; 26 27 WeakPointer(Type* object); 28 ~WeakPointer(); 29 30 private: 31 void _GetUnchecked(); 32 33 private: 34 vint32 fUseCount; 35 Type* fObject; 36 }; 37 38 template<typename Type> 39 class WeakReferenceable { 40 public: 41 WeakReferenceable(Type* object); 42 ~WeakReferenceable(); 43 44 void AddReference() 45 { fPointer->_GetUnchecked(); } 46 47 bool RemoveReference() 48 { return fPointer->Put(); } 49 50 int32 CountReferences() const 51 { return fPointer->UseCount(); } 52 53 WeakPointer<Type>* GetWeakPointer(); 54 55 protected: 56 WeakPointer<Type>* fPointer; 57 }; 58 59 template<typename Type> 60 class WeakReference { 61 public: 62 WeakReference() 63 : 64 fPointer(NULL), 65 fObject(NULL) 66 { 67 } 68 69 WeakReference(Type* object) 70 : 71 fPointer(NULL), 72 fObject(NULL) 73 { 74 SetTo(object); 75 } 76 77 WeakReference(WeakPointer<Type>& other) 78 : 79 fPointer(NULL), 80 fObject(NULL) 81 { 82 SetTo(&other); 83 } 84 85 WeakReference(WeakPointer<Type>* other) 86 : 87 fPointer(NULL), 88 fObject(NULL) 89 { 90 SetTo(other); 91 } 92 93 WeakReference(const WeakReference<Type>& other) 94 : 95 fPointer(NULL), 96 fObject(NULL) 97 { 98 SetTo(other.fPointer); 99 } 100 101 ~WeakReference() 102 { 103 Unset(); 104 } 105 106 void SetTo(Type* object) 107 { 108 Unset(); 109 110 if (object != NULL) { 111 fPointer = object->GetWeakPointer(); 112 fObject = fPointer->Get(); 113 } 114 } 115 116 void SetTo(WeakPointer<Type>* pointer) 117 { 118 Unset(); 119 120 if (pointer != NULL) { 121 fPointer = pointer; 122 fPointer->AddReference(); 123 fObject = pointer->Get(); 124 } 125 } 126 127 void Unset() 128 { 129 if (fPointer != NULL) { 130 if (fObject != NULL) { 131 fPointer->Put(); 132 fObject = NULL; 133 } 134 fPointer->RemoveReference(); 135 fPointer = NULL; 136 } 137 } 138 139 Type* Get() const 140 { 141 return fObject; 142 } 143 144 Type* Detach() 145 { 146 Type* object = fObject; 147 Unset(); 148 return object; 149 } 150 151 Type& operator*() const 152 { 153 return *fObject; 154 } 155 156 operator Type*() const 157 { 158 return fObject; 159 } 160 161 Type* operator->() const 162 { 163 return fObject; 164 } 165 166 WeakReference& operator=(const WeakReference<Type>& other) 167 { 168 if (this == &other) 169 return *this; 170 171 SetTo(other.fPointer); 172 return *this; 173 } 174 175 WeakReference& operator=(const Type& other) 176 { 177 SetTo(&other); 178 return *this; 179 } 180 181 WeakReference& operator=(WeakPointer<Type>& other) 182 { 183 SetTo(&other); 184 return *this; 185 } 186 187 WeakReference& operator=(WeakPointer<Type>* other) 188 { 189 SetTo(other); 190 return *this; 191 } 192 193 bool operator==(const WeakReference<Type>& other) const 194 { 195 return fPointer == other.fPointer; 196 } 197 198 bool operator!=(const WeakReference<Type>& other) const 199 { 200 return fPointer != other.fPointer; 201 } 202 203 private: 204 WeakPointer<Type>* fPointer; 205 Type* fObject; 206 }; 207 208 209 // #pragma mark - 210 211 212 template<typename Type> 213 inline Type* 214 WeakPointer<Type>::Get() 215 { 216 int32 count = -11; 217 218 do { 219 count = atomic_get(&fUseCount); 220 if (count == 0) 221 return NULL; 222 } while (atomic_test_and_set(&fUseCount, count + 1, count) != count); 223 224 return fObject; 225 } 226 227 228 template<typename Type> 229 inline bool 230 WeakPointer<Type>::Put() 231 { 232 if (atomic_add(&fUseCount, -1) == 1) { 233 delete fObject; 234 return true; 235 } 236 237 return false; 238 } 239 240 241 template<typename Type> 242 inline int32 243 WeakPointer<Type>::UseCount() const 244 { 245 return fUseCount; 246 } 247 248 249 template<typename Type> 250 inline 251 WeakPointer<Type>::WeakPointer(Type* object) 252 : 253 fUseCount(1), 254 fObject(object) 255 { 256 } 257 258 259 template<typename Type> 260 inline 261 WeakPointer<Type>::~WeakPointer() 262 { 263 } 264 265 266 template<typename Type> 267 inline void 268 WeakPointer<Type>::_GetUnchecked() 269 { 270 atomic_add(&fUseCount, 1); 271 } 272 273 274 // #pragma - 275 276 277 template<typename Type> 278 inline 279 WeakReferenceable<Type>::WeakReferenceable(Type* object) 280 : 281 fPointer(new WeakPointer<Type>(object)) 282 { 283 } 284 285 286 template<typename Type> 287 inline 288 WeakReferenceable<Type>::~WeakReferenceable() 289 { 290 fPointer->RemoveReference(); 291 } 292 293 294 template<typename Type> 295 inline WeakPointer<Type>* 296 WeakReferenceable<Type>::GetWeakPointer() 297 { 298 fPointer->AddReference(); 299 return fPointer; 300 } 301 302 } // namespace BPrivate 303 304 using BPrivate::WeakReferenceable; 305 using BPrivate::WeakPointer; 306 using BPrivate::WeakReference; 307 308 #endif // _WEAK_REFERENCEABLE_H 309