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 vint32 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 ~BWeakReference() 91 { 92 Unset(); 93 } 94 95 void SetTo(Type* object) 96 { 97 Unset(); 98 99 if (object != NULL) 100 fPointer = object->GetWeakPointer(); 101 } 102 103 void SetTo(const BWeakReference<Type>& other) 104 { 105 Unset(); 106 107 if (other.fPointer) { 108 fPointer = other.fPointer; 109 fPointer->AcquireReference(); 110 } 111 } 112 113 void SetTo(const BReference<Type>& other) 114 { 115 SetTo(other.Get()); 116 } 117 118 void Unset() 119 { 120 if (fPointer != NULL) { 121 fPointer->ReleaseReference(); 122 fPointer = NULL; 123 } 124 } 125 126 bool IsAlive() 127 { 128 if (fPointer == NULL) 129 return false; 130 Type* object = static_cast<Type*>(fPointer->Get()); 131 if (object == NULL) 132 return false; 133 fPointer->Put(); 134 return true; 135 } 136 137 BReference<Type> GetReference() 138 { 139 Type* object = static_cast<Type*>(fPointer->Get()); 140 return BReference<Type>(object, true); 141 } 142 143 BWeakReference& operator=(const BWeakReference<Type>& other) 144 { 145 if (this == &other) 146 return *this; 147 148 SetTo(other.fPointer); 149 return *this; 150 } 151 152 BWeakReference& operator=(const Type& other) 153 { 154 SetTo(&other); 155 return *this; 156 } 157 158 BWeakReference& operator=(Type* other) 159 { 160 SetTo(other); 161 return *this; 162 } 163 164 BWeakReference& operator=(const BReference<Type>& other) 165 { 166 SetTo(other.Get()); 167 return *this; 168 } 169 170 bool operator==(const BWeakReference<Type>& other) const 171 { 172 return fPointer == other.fPointer; 173 } 174 175 bool operator!=(const BWeakReference<Type>& other) const 176 { 177 return fPointer != other.fPointer; 178 } 179 180 private: 181 WeakPointer* fPointer; 182 }; 183 184 185 // #pragma mark - 186 187 188 inline 189 WeakPointer::WeakPointer(BWeakReferenceable* object) 190 : 191 fUseCount(1), 192 fObject(object) 193 { 194 } 195 196 197 inline 198 WeakPointer::~WeakPointer() 199 { 200 } 201 202 203 inline BWeakReferenceable* 204 WeakPointer::Get() 205 { 206 int32 count = -11; 207 208 do { 209 count = atomic_get(&fUseCount); 210 if (count == 0) 211 return NULL; 212 } while (atomic_test_and_set(&fUseCount, count + 1, count) != count); 213 214 return fObject; 215 } 216 217 218 inline bool 219 WeakPointer::Put() 220 { 221 if (atomic_add(&fUseCount, -1) == 1) { 222 delete fObject; 223 return true; 224 } 225 226 return false; 227 } 228 229 230 inline int32 231 WeakPointer::UseCount() const 232 { 233 return fUseCount; 234 } 235 236 237 inline void 238 WeakPointer::GetUnchecked() 239 { 240 atomic_add(&fUseCount, 1); 241 } 242 243 244 // #pragma - 245 246 247 inline 248 BWeakReferenceable::BWeakReferenceable() 249 : 250 fPointer(new(std::nothrow) WeakPointer(this)) 251 { 252 } 253 254 255 inline 256 BWeakReferenceable::~BWeakReferenceable() 257 { 258 fPointer->ReleaseReference(); 259 } 260 261 262 inline status_t 263 BWeakReferenceable::InitCheck() 264 { 265 if (fPointer == NULL) 266 return B_NO_MEMORY; 267 return B_OK; 268 } 269 270 271 inline WeakPointer* 272 BWeakReferenceable::GetWeakPointer() 273 { 274 fPointer->AcquireReference(); 275 return fPointer; 276 } 277 278 } // namespace BPrivate 279 280 using BPrivate::BWeakReferenceable; 281 using BPrivate::BWeakReference; 282 283 #endif // _WEAK_REFERENCEABLE_H 284