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 47 void AcquireReference() 48 { fPointer->GetUnchecked(); } 49 50 bool ReleaseReference() 51 { return fPointer->Put(); } 52 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: 65 BWeakReference() 66 : 67 fPointer(NULL) 68 { 69 } 70 71 BWeakReference(Type* object) 72 : 73 fPointer(NULL) 74 { 75 SetTo(object); 76 } 77 78 BWeakReference(const BWeakReference<Type>& other) 79 : 80 fPointer(NULL) 81 { 82 SetTo(other); 83 } 84 85 BWeakReference(const BReference<Type>& other) 86 : 87 fPointer(NULL) 88 { 89 SetTo(other); 90 } 91 92 template<typename OtherType> 93 BWeakReference(const BReference<OtherType>& other) 94 : 95 fPointer(NULL) 96 { 97 SetTo(other.Get()); 98 } 99 100 template<typename OtherType> 101 BWeakReference(const BWeakReference<OtherType>& other) 102 : 103 fPointer(NULL) 104 { 105 SetTo(other); 106 } 107 108 ~BWeakReference() 109 { 110 Unset(); 111 } 112 113 void SetTo(Type* object) 114 { 115 Unset(); 116 117 if (object != NULL) 118 fPointer = object->GetWeakPointer(); 119 } 120 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> 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 147 void SetTo(const BReference<Type>& other) 148 { 149 SetTo(other.Get()); 150 } 151 152 void Unset() 153 { 154 if (fPointer != NULL) { 155 fPointer->ReleaseReference(); 156 fPointer = NULL; 157 } 158 } 159 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 171 BReference<Type> GetReference() 172 { 173 Type* object = static_cast<Type*>(fPointer->Get()); 174 return BReference<Type>(object, true); 175 } 176 177 BWeakReference& operator=(const BWeakReference<Type>& other) 178 { 179 if (this == &other) 180 return *this; 181 182 SetTo(other); 183 return *this; 184 } 185 186 BWeakReference& operator=(Type* other) 187 { 188 SetTo(other); 189 return *this; 190 } 191 192 BWeakReference& operator=(const BReference<Type>& other) 193 { 194 SetTo(other.Get()); 195 return *this; 196 } 197 198 template<typename OtherType> 199 BWeakReference& operator=(const BReference<OtherType>& other) 200 { 201 SetTo(other.Get()); 202 return *this; 203 } 204 205 template<typename OtherType> 206 BWeakReference& operator=(const BWeakReference<OtherType>& other) 207 { 208 SetTo(other); 209 return *this; 210 } 211 212 bool operator==(const BWeakReference<Type>& other) const 213 { 214 return fPointer == other.fPointer; 215 } 216 217 bool operator!=(const BWeakReference<Type>& other) const 218 { 219 return fPointer != other.fPointer; 220 } 221 222 /*! Do not use this if you do not know what you are doing. The WeakPointer 223 is for internal use only. 224 */ 225 const WeakPointer* PrivatePointer() const 226 { 227 return fPointer; 228 } 229 230 private: 231 WeakPointer* fPointer; 232 }; 233 234 235 } // namespace BPrivate 236 237 using BPrivate::BWeakReferenceable; 238 using BPrivate::BWeakReference; 239 240 #endif // _WEAK_REFERENCEABLE_H 241