1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_REFERENCED_H 17 #define FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_REFERENCED_H 18 19 #include <string> 20 21 #include "base/memory/memory_monitor.h" 22 #include "base/memory/ref_counter.h" 23 #include "base/utils/macros.h" 24 25 #define ACE_REMOVE(...) 26 27 namespace OHOS::Ace { 28 29 template<class T> 30 class RefPtr; 31 template<class T> 32 class WeakPtr; 33 34 // Inherit this class to use 'RefPtr' and 'WeakPtr' to manage pointer of instance. 35 class Referenced { 36 public: 37 // Use raw pointer to construct 'RefPtr' and 'WeakPtr'. 38 template<class T> Claim(T * rawPtr)39 static RefPtr<T> Claim(T* rawPtr) 40 { 41 #ifdef ACE_MEMORY_MONITOR 42 MemoryMonitor::GetInstance().Update(rawPtr, static_cast<Referenced*>(rawPtr)); 43 #endif 44 return RefPtr<T>(rawPtr); 45 } 46 template<class T> WeakClaim(T * rawPtr)47 static WeakPtr<T> WeakClaim(T* rawPtr) 48 { 49 return WeakPtr<T>(rawPtr); 50 } 51 52 // 'Referenced::MakeRefPtr' is used to create new instance inherited from 'Referenced', 53 // and manager its pointer using 'RefPtr'. 54 template<class T, class... Args> MakeRefPtr(Args &&...args)55 static RefPtr<T> MakeRefPtr(Args&&... args) 56 { 57 return Claim(new T(std::forward<Args>(args)...)); 58 } 59 60 // Get raw pointer from 'RefPtr'. 61 template<class T> RawPtr(const RefPtr<T> & ptr)62 static T* RawPtr(const RefPtr<T>& ptr) 63 { 64 return ptr.rawPtr_; 65 } 66 IncRefCount()67 int32_t IncRefCount() 68 { 69 return refCounter_->IncStrongRef(); 70 } DecRefCount()71 int32_t DecRefCount() 72 { 73 int32_t refCount = refCounter_->DecStrongRef(); 74 if (refCount == 0 && MaybeRelease()) { 75 // Release this instance, while its strong reference have reduced to zero. 76 delete this; 77 } 78 return refCount; 79 } 80 #ifdef ACE_MEMORY_MONITOR RefCount()81 int32_t RefCount() const 82 { 83 return refCounter_->StrongRefCount(); 84 } 85 #endif 86 87 protected: 88 explicit Referenced(bool threadSafe = true) 89 : refCounter_(threadSafe ? ThreadSafeRef::Create() : ThreadUnsafeRef::Create()) 90 { 91 #ifdef ACE_MEMORY_MONITOR 92 MemoryMonitor::GetInstance().Add(this); 93 #endif 94 } 95 ~Referenced()96 virtual ~Referenced() 97 { 98 // Decrease weak reference count held by 'Referenced' itself. 99 refCounter_->DecWeakRef(); 100 refCounter_ = nullptr; 101 #ifdef ACE_MEMORY_MONITOR 102 MemoryMonitor::GetInstance().Remove(this); 103 #endif 104 } 105 MaybeRelease()106 virtual bool MaybeRelease() 107 { 108 return true; 109 } 110 111 private: 112 template<class T> 113 friend class RefPtr; 114 template<class T> 115 friend class WeakPtr; 116 117 RefCounter* refCounter_ { nullptr }; 118 119 ACE_DISALLOW_COPY_AND_MOVE(Referenced); 120 }; 121 122 // Use reference count to manager instance inherited from 'Referenced'. 123 // Implicit conversion is necessary in some cases, so remove 'explicit' from construct function. 124 template<class T> 125 class RefPtr final { 126 public: 127 // Basic constructors. 128 RefPtr() = default; RefPtr(std::nullptr_t)129 ACE_REMOVE(explicit) RefPtr(std::nullptr_t) {} 130 // Basic copy and move constructors. RefPtr(const RefPtr & other)131 ACE_REMOVE(explicit) RefPtr(const RefPtr& other) : RefPtr(other.rawPtr_) {} RefPtr(RefPtr && other)132 ACE_REMOVE(explicit) RefPtr(RefPtr&& other) : rawPtr_(other.rawPtr_) 133 { 134 other.rawPtr_ = nullptr; 135 } 136 // Construct instance by other 'RefPtr' that inherited from type 'T'. 137 template<class O> ACE_REMOVE(explicit)138 ACE_REMOVE(explicit) RefPtr(const RefPtr<O>& other) : RefPtr(other.rawPtr_) {} 139 template<class O> ACE_REMOVE(explicit)140 ACE_REMOVE(explicit) RefPtr(RefPtr<O>&& other) : rawPtr_(other.rawPtr_) 141 { 142 other.rawPtr_ = nullptr; 143 } 144 ~RefPtr()145 ~RefPtr() 146 { 147 if (rawPtr_ != nullptr) { 148 // Decrease strong reference count. 149 rawPtr_->DecRefCount(); 150 rawPtr_ = nullptr; 151 } 152 } 153 Swap(RefPtr & other)154 void Swap(RefPtr& other) 155 { 156 std::swap(rawPtr_, other.rawPtr_); 157 } Swap(RefPtr && other)158 void Swap(RefPtr&& other) 159 { 160 Swap(other); 161 } Reset()162 void Reset() 163 { 164 Swap(RefPtr()); 165 } 166 167 T* operator->() const 168 { 169 return rawPtr_; 170 } 171 T& operator*() const 172 { 173 ACE_DCHECK(rawPtr_ != nullptr); 174 return *rawPtr_; 175 } 176 operator bool() const 177 { 178 return rawPtr_ != nullptr; 179 } 180 181 // Use 'Swap' to implement overloaded operator '='. 182 // Construct a temporary 'RefPtr' by different parameters to increase strong reference count of the new instance, 183 // swap with 'this', and then decrease strong reference of the old instance while destroying the temporary 'RefPtr'. 184 RefPtr& operator=(const RefPtr& other) 185 { 186 if (this != &other) { 187 Swap(RefPtr(other)); 188 } 189 return *this; 190 } 191 RefPtr& operator=(RefPtr&& other) 192 { 193 if (this != &other) { 194 Swap(RefPtr(std::move(other))); 195 } 196 return *this; 197 } 198 199 template<class O> 200 RefPtr& operator=(O* rawPtr) 201 { 202 Swap(RefPtr(rawPtr)); 203 return *this; 204 } 205 template<class O> 206 RefPtr& operator=(const RefPtr<O>& other) 207 { 208 Swap(RefPtr(other)); 209 return *this; 210 } 211 template<class O> 212 RefPtr& operator=(RefPtr<O>&& other) 213 { 214 Swap(RefPtr(std::move(other))); 215 return *this; 216 } 217 218 // Comparing pointer of reference counter to implement Overloaded operator '==' and '!='. 219 template<class O> 220 bool operator==(const O* rawPtr) const 221 { 222 if (rawPtr_ == nullptr) { 223 return rawPtr == nullptr; 224 } 225 return rawPtr != nullptr && rawPtr_->refCounter_ == rawPtr->refCounter_; 226 } 227 template<class O> 228 bool operator!=(const O* rawPtr) const 229 { 230 return !operator==(rawPtr); 231 } 232 233 template<class O> 234 bool operator==(const RefPtr<O>& other) const 235 { 236 return *this == other.rawPtr_; 237 } 238 template<class O> 239 bool operator!=(const RefPtr<O>& other) const 240 { 241 return !operator==(other); 242 } 243 244 template<class O> 245 bool operator==(const WeakPtr<O>& weak) const 246 { 247 return weak == *this; 248 } 249 template<class O> 250 bool operator!=(const WeakPtr<O>& weak) const 251 { 252 return !operator==(weak); 253 } 254 255 bool operator==(std::nullptr_t) const 256 { 257 return rawPtr_ == nullptr; 258 } 259 bool operator!=(std::nullptr_t) const 260 { 261 return rawPtr_ != nullptr; 262 } 263 264 // Overload '<' is useful for 'std::map', 'std::set' and so on. 265 template<class O> 266 bool operator<(const RefPtr<O>& other) const 267 { 268 if (rawPtr_ == nullptr) { 269 return other.rawPtr_ != nullptr; 270 } 271 return other.rawPtr_ != nullptr && rawPtr_->refCounter_ < other.rawPtr_->refCounter_; 272 } 273 274 private: 275 // Construct instance by raw pointer. 276 // 'WeakPtr' may construct 'RefPtr' without increasing its strong reference count, 277 // because strong reference count is already increased in 'WeakPtr' while upgrading. 278 // In that case, 'forceIncRef' should be 'false'. rawPtr_(rawPtr)279 explicit RefPtr(T* rawPtr, bool forceIncRef = true) : rawPtr_(rawPtr) 280 { 281 if (rawPtr_ != nullptr && forceIncRef) { 282 // Increase strong reference count for holding instance. 283 rawPtr_->IncRefCount(); 284 } 285 } 286 287 friend class Referenced; 288 template<class O> 289 friend class RefPtr; 290 template<class O> 291 friend class WeakPtr; 292 293 T* rawPtr_ { nullptr }; 294 }; 295 296 // Working with 'RefPtr' to resolve 'circular reference'. 297 // Implicit conversion is necessary in some cases, so remove 'explicit' from construct function. 298 template<class T> 299 class WeakPtr final { 300 public: 301 // Basic constructors. 302 WeakPtr() = default; WeakPtr(std::nullptr_t)303 ACE_REMOVE(explicit) WeakPtr(std::nullptr_t) {} 304 // Basic copy and move constructors. WeakPtr(const WeakPtr & other)305 ACE_REMOVE(explicit) WeakPtr(const WeakPtr& other) : WeakPtr(other.unsafeRawPtr_, other.refCounter_) {} WeakPtr(WeakPtr && other)306 ACE_REMOVE(explicit) WeakPtr(WeakPtr&& other) : unsafeRawPtr_(other.unsafeRawPtr_), refCounter_(other.refCounter_) 307 { 308 other.unsafeRawPtr_ = nullptr; 309 other.refCounter_ = nullptr; 310 } 311 // Construct instance by other 'WeakPtr' that inherited from type 'T'. 312 template<class O> ACE_REMOVE(explicit)313 ACE_REMOVE(explicit) WeakPtr(const WeakPtr<O>& other) : WeakPtr(other.unsafeRawPtr_, other.refCounter_) {} 314 template<class O> ACE_REMOVE(explicit)315 ACE_REMOVE(explicit) WeakPtr(WeakPtr<O>&& other) 316 : unsafeRawPtr_(other.unsafeRawPtr_), refCounter_(other.refCounter_) 317 { 318 other.unsafeRawPtr_ = nullptr; 319 other.refCounter_ = nullptr; 320 } 321 // Construct instance by 'RefPtr' that inherited from type 'T' or 'T' itself. 322 template<class O> ACE_REMOVE(explicit)323 ACE_REMOVE(explicit) WeakPtr(const RefPtr<O>& other) : WeakPtr(other.rawPtr_) {} 324 ~WeakPtr()325 ~WeakPtr() 326 { 327 // Decrease weak reference count while releasing reference counter. 328 if (refCounter_ != nullptr) { 329 refCounter_->DecWeakRef(); 330 refCounter_ = nullptr; 331 unsafeRawPtr_ = nullptr; 332 } 333 } 334 Swap(WeakPtr & other)335 void Swap(WeakPtr& other) 336 { 337 std::swap(unsafeRawPtr_, other.unsafeRawPtr_); 338 std::swap(refCounter_, other.refCounter_); 339 } Swap(WeakPtr && other)340 void Swap(WeakPtr&& other) 341 { 342 Swap(other); 343 } Reset()344 void Reset() 345 { 346 Swap(WeakPtr()); 347 } 348 Upgrade()349 RefPtr<T> Upgrade() const 350 { 351 // A 'WeakPtr' could upgrade to 'RefPtr' if this instance is still alive. 352 return refCounter_ != nullptr && refCounter_->TryIncStrongRef() > 0 ? RefPtr<T>(unsafeRawPtr_, false) : nullptr; 353 } Invalid()354 bool Invalid() const 355 { 356 return refCounter_ == nullptr || refCounter_->StrongRefCount() == 0; 357 } 358 359 // Use 'Swap' to implement overloaded operator '=', just like 'RefPtr'. 360 WeakPtr& operator=(const WeakPtr& other) 361 { 362 if (this != &other) { 363 Swap(WeakPtr(other)); 364 } 365 return *this; 366 } 367 WeakPtr& operator=(WeakPtr&& other) 368 { 369 if (this != &other) { 370 Swap(WeakPtr(std::move(other))); 371 } 372 return *this; 373 } 374 375 template<class O> 376 WeakPtr& operator=(O* rawPtr) 377 { 378 Swap(WeakPtr(rawPtr)); 379 return *this; 380 } 381 template<class O> 382 WeakPtr& operator=(const WeakPtr<O>& other) 383 { 384 Swap(WeakPtr(other)); 385 return *this; 386 } 387 template<class O> 388 WeakPtr& operator=(WeakPtr<O>&& other) 389 { 390 Swap(WeakPtr(std::move(other))); 391 return *this; 392 } 393 template<class O> 394 WeakPtr& operator=(const RefPtr<O>& other) 395 { 396 Swap(WeakPtr(other.rawPtr_)); 397 return *this; 398 } 399 400 // Comparing pointer of reference counter to implement Overloaded operator '==' and '!=', just like 'RefPtr'. 401 template<class O> 402 bool operator==(const O* rawPtr) const 403 { 404 if (refCounter_ == nullptr) { 405 return rawPtr == nullptr; 406 } 407 return rawPtr != nullptr && refCounter_ == rawPtr->refCounter_; 408 } 409 template<class O> 410 bool operator!=(const O* rawPtr) const 411 { 412 return !operator==(rawPtr); 413 } 414 415 template<class O> 416 bool operator==(const WeakPtr<O>& other) const 417 { 418 return refCounter_ == other.refCounter_; 419 } 420 template<class O> 421 bool operator!=(const WeakPtr<O>& other) const 422 { 423 return !operator==(other); 424 } 425 426 template<class O> 427 bool operator==(const RefPtr<O>& strong) const 428 { 429 return strong.rawPtr_ != nullptr ? strong.rawPtr_->refCounter_ == refCounter_ : refCounter_ == nullptr; 430 } 431 template<class O> 432 bool operator!=(const RefPtr<O>& strong) const 433 { 434 return !operator==(strong); 435 } 436 437 // Overload '<' is useful for 'std::map', 'std::set' and so on, just like 'RefPtr'. 438 template<class O> 439 bool operator<(const WeakPtr<O>& other) const 440 { 441 return refCounter_ < other.refCounter_; 442 } 443 444 private: 445 // Construct instance by raw pointer. WeakPtr(T * rawPtr)446 explicit WeakPtr(T* rawPtr) : WeakPtr(rawPtr, rawPtr != nullptr ? rawPtr->refCounter_ : nullptr) {} 447 template<class O> WeakPtr(O * rawPtr,RefCounter * aceRef)448 WeakPtr(O* rawPtr, RefCounter* aceRef) : unsafeRawPtr_(rawPtr), refCounter_(aceRef) 449 { 450 if (refCounter_) { 451 refCounter_->IncWeakRef(); 452 } 453 } 454 455 friend class Referenced; 456 template<class O> 457 friend class WeakPtr; 458 459 // Notice: Raw pointer of instance is kept, but NEVER use it except succeed to upgrade to 'RefPtr'. 460 T* unsafeRawPtr_ { nullptr }; 461 RefCounter* refCounter_ { nullptr }; 462 }; 463 464 } // namespace OHOS::Ace 465 466 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_REFERENCED_H 467