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 friend class BWeakReferenceable; 34 35 int32 fUseCount; 36 BWeakReferenceable* fObject; 37 }; 38 39 40 class BWeakReferenceable { 41 public: 42 BWeakReferenceable(); 43 virtual ~BWeakReferenceable(); 44 45 status_t InitCheck(); 46 AcquireReference()47 void AcquireReference() 48 { fPointer->GetUnchecked(); } 49 ReleaseReference()50 bool ReleaseReference() 51 { return fPointer->Put(); } 52 CountReferences()53 int32 CountReferences() const 54 { return fPointer->UseCount(); } 55 56 WeakPointer* GetWeakPointer(); 57 private: 58 WeakPointer* fPointer; 59 }; 60 61 62 template<typename Type> 63 class BWeakReference { 64 public: BWeakReference()65 BWeakReference() 66 : 67 fPointer(NULL) 68 { 69 } 70 BWeakReference(Type * object)71 BWeakReference(Type* object) 72 : 73 fPointer(NULL) 74 { 75 SetTo(object); 76 } 77 BWeakReference(const BWeakReference<Type> & other)78 BWeakReference(const BWeakReference<Type>& other) 79 : 80 fPointer(NULL) 81 { 82 SetTo(other); 83 } 84 BWeakReference(const BReference<Type> & other)85 BWeakReference(const BReference<Type>& other) 86 : 87 fPointer(NULL) 88 { 89 SetTo(other); 90 } 91 92 template<typename OtherType> BWeakReference(const BReference<OtherType> & other)93 BWeakReference(const BReference<OtherType>& other) 94 : 95 fPointer(NULL) 96 { 97 SetTo(other.Get()); 98 } 99 100 template<typename OtherType> BWeakReference(const BWeakReference<OtherType> & other)101 BWeakReference(const BWeakReference<OtherType>& other) 102 : 103 fPointer(NULL) 104 { 105 SetTo(other); 106 } 107 ~BWeakReference()108 ~BWeakReference() 109 { 110 Unset(); 111 } 112 SetTo(Type * object)113 void SetTo(Type* object) 114 { 115 Unset(); 116 117 if (object != NULL) 118 fPointer = object->GetWeakPointer(); 119 } 120 SetTo(const BWeakReference<Type> & other)121 void SetTo(const BWeakReference<Type>& other) 122 { 123 Unset(); 124 125 if (other.fPointer) { 126 fPointer = other.fPointer; 127 fPointer->AcquireReference(); 128 } 129 } 130 131 template<typename OtherType> SetTo(const BWeakReference<OtherType> & other)132 void SetTo(const BWeakReference<OtherType>& other) 133 { 134 // Just a compiler check if the types are compatible. 135 OtherType* otherDummy = NULL; 136 Type* dummy = otherDummy; 137 dummy = NULL; 138 139 Unset(); 140 141 if (other.PrivatePointer()) { 142 fPointer = const_cast<WeakPointer*>(other.PrivatePointer()); 143 fPointer->AcquireReference(); 144 } 145 } 146 SetTo(const BReference<Type> & other)147 void SetTo(const BReference<Type>& other) 148 { 149 SetTo(other.Get()); 150 } 151 Unset()152 void Unset() 153 { 154 if (fPointer != NULL) { 155 fPointer->ReleaseReference(); 156 fPointer = NULL; 157 } 158 } 159 IsAlive()160 bool IsAlive() 161 { 162 if (fPointer == NULL) 163 return false; 164 Type* object = static_cast<Type*>(fPointer->Get()); 165 if (object == NULL) 166 return false; 167 fPointer->Put(); 168 return true; 169 } 170 GetReference()171 BReference<Type> GetReference() 172 { 173 if (fPointer == NULL) 174 return BReference<Type>(); 175 176 Type* object = static_cast<Type*>(fPointer->Get()); 177 return BReference<Type>(object, true); 178 } 179 180 BWeakReference& operator=(const BWeakReference<Type>& other) 181 { 182 if (this == &other) 183 return *this; 184 185 SetTo(other); 186 return *this; 187 } 188 189 BWeakReference& operator=(Type* other) 190 { 191 SetTo(other); 192 return *this; 193 } 194 195 BWeakReference& operator=(const BReference<Type>& other) 196 { 197 SetTo(other.Get()); 198 return *this; 199 } 200 201 template<typename OtherType> 202 BWeakReference& operator=(const BReference<OtherType>& other) 203 { 204 SetTo(other.Get()); 205 return *this; 206 } 207 208 template<typename OtherType> 209 BWeakReference& operator=(const BWeakReference<OtherType>& other) 210 { 211 SetTo(other); 212 return *this; 213 } 214 215 bool operator==(const BWeakReference<Type>& other) const 216 { 217 return fPointer == other.fPointer; 218 } 219 220 bool operator!=(const BWeakReference<Type>& other) const 221 { 222 return fPointer != other.fPointer; 223 } 224 225 /*! Do not use this if you do not know what you are doing. The WeakPointer 226 is for internal use only. 227 */ PrivatePointer()228 const WeakPointer* PrivatePointer() const 229 { 230 return fPointer; 231 } 232 233 private: 234 WeakPointer* fPointer; 235 }; 236 237 238 } // namespace BPrivate 239 240 using BPrivate::BWeakReferenceable; 241 using BPrivate::BWeakReference; 242 243 #endif // _WEAK_REFERENCEABLE_H 244