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 if (MemoryMonitor::IsEnable()) { 42 MemoryMonitor::GetInstance().Update(rawPtr, static_cast<Referenced*>(rawPtr)); 43 } 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 67 template<class T> UnsafeRawPtr(const WeakPtr<T> & ptr)68 static T* UnsafeRawPtr(const WeakPtr<T>& ptr) 69 { 70 return ptr.unsafeRawPtr_; 71 } 72 IncRefCount()73 void IncRefCount() 74 { 75 refCounter_->IncStrongRef(); 76 } DecRefCount()77 void DecRefCount() 78 { 79 int32_t refCount = refCounter_->DecStrongRef(); 80 if (refCount == 0 && MaybeRelease()) { 81 // Release this instance, while its strong reference have reduced to zero. 82 delete this; 83 } 84 } 85 RefCount()86 int32_t RefCount() const 87 { 88 return refCounter_->StrongRefCount(); 89 } 90 91 protected: 92 explicit Referenced(bool threadSafe = true) 93 : refCounter_(threadSafe ? ThreadSafeRef::Create() : ThreadUnsafeRef::Create()) 94 { 95 if (MemoryMonitor::IsEnable()) { 96 MemoryMonitor::GetInstance().Add(this); 97 } 98 } 99 ~Referenced()100 virtual ~Referenced() 101 { 102 // Decrease weak reference count held by 'Referenced' itself. 103 refCounter_->DecWeakRef(); 104 refCounter_ = nullptr; 105 if (MemoryMonitor::IsEnable()) { 106 MemoryMonitor::GetInstance().Remove(this); 107 } 108 } 109 MaybeRelease()110 virtual bool MaybeRelease() 111 { 112 return true; 113 } 114 115 private: 116 template<class T> 117 friend class RefPtr; 118 template<class T> 119 friend class WeakPtr; 120 // Forbid getting raw pointer from rvalue 'RefPtr'. 121 template<class T> 122 static T* RawPtr(const RefPtr<T>&& ptr) = delete; 123 124 RefCounter* refCounter_ { nullptr }; 125 126 ACE_DISALLOW_COPY_AND_MOVE(Referenced); 127 }; 128 129 // Use reference count to manager instance inherited from 'Referenced'. 130 // Implicit conversion is necessary in some cases, so remove 'explicit' from construct function. 131 template<class T> 132 class RefPtr final { 133 public: 134 // Basic constructors. 135 RefPtr() = default; RefPtr(std::nullptr_t)136 ACE_REMOVE(explicit) RefPtr(std::nullptr_t) {} 137 // Basic copy and move constructors. RefPtr(const RefPtr & other)138 ACE_REMOVE(explicit) RefPtr(const RefPtr& other) : RefPtr(other.rawPtr_) {} RefPtr(RefPtr && other)139 ACE_REMOVE(explicit) RefPtr(RefPtr&& other) : rawPtr_(other.rawPtr_) 140 { 141 other.rawPtr_ = nullptr; 142 } 143 // Construct instance by other 'RefPtr' that inherited from type 'T'. 144 template<class O> ACE_REMOVE(explicit)145 ACE_REMOVE(explicit) RefPtr(const RefPtr<O>& other) : RefPtr(other.rawPtr_) {} 146 template<class O> ACE_REMOVE(explicit)147 ACE_REMOVE(explicit) RefPtr(RefPtr<O>&& other) : rawPtr_(other.rawPtr_) 148 { 149 other.rawPtr_ = nullptr; 150 } 151 ~RefPtr()152 ~RefPtr() 153 { 154 if (rawPtr_ != nullptr) { 155 // Decrease strong reference count. 156 rawPtr_->DecRefCount(); 157 rawPtr_ = nullptr; 158 } 159 } 160 Swap(RefPtr & other)161 void Swap(RefPtr& other) 162 { 163 std::swap(rawPtr_, other.rawPtr_); 164 } Swap(RefPtr && other)165 void Swap(RefPtr&& other) 166 { 167 Swap(other); 168 } Reset()169 void Reset() 170 { 171 Swap(RefPtr()); 172 } 173 174 T* operator->() const 175 { 176 return rawPtr_; 177 } 178 T& operator*() const 179 { 180 ACE_DCHECK(rawPtr_ != nullptr); 181 return *rawPtr_; 182 } 183 operator bool() const 184 { 185 return rawPtr_ != nullptr; 186 } 187 GetRawPtr()188 T* GetRawPtr() const 189 { 190 return rawPtr_; 191 } 192 193 // Use 'Swap' to implement overloaded operator '='. 194 // Construct a temporary 'RefPtr' by different parameters to increase strong reference count of the new instance, 195 // swap with 'this', and then decrease strong reference of the old instance while destroying the temporary 'RefPtr'. 196 RefPtr& operator=(const RefPtr& other) 197 { 198 if (this != &other) { 199 Swap(RefPtr(other)); 200 } 201 return *this; 202 } 203 RefPtr& operator=(RefPtr&& other) 204 { 205 if (this != &other) { 206 Swap(RefPtr(std::move(other))); 207 } 208 return *this; 209 } 210 211 template<class O> 212 RefPtr& operator=(O* rawPtr) 213 { 214 Swap(RefPtr(rawPtr)); 215 return *this; 216 } 217 template<class O> 218 RefPtr& operator=(const RefPtr<O>& other) 219 { 220 Swap(RefPtr(other)); 221 return *this; 222 } 223 template<class O> 224 RefPtr& operator=(RefPtr<O>&& other) 225 { 226 Swap(RefPtr(std::move(other))); 227 return *this; 228 } 229 230 // Comparing pointer of reference counter to implement Overloaded operator '==' and '!='. 231 template<class O> 232 bool operator==(const O* rawPtr) const 233 { 234 if (rawPtr_ == nullptr) { 235 return rawPtr == nullptr; 236 } 237 return rawPtr != nullptr && rawPtr_->refCounter_ == rawPtr->refCounter_; 238 } 239 template<class O> 240 bool operator!=(const O* rawPtr) const 241 { 242 return !operator==(rawPtr); 243 } 244 245 template<class O> 246 bool operator==(const RefPtr<O>& other) const 247 { 248 return *this == other.rawPtr_; 249 } 250 template<class O> 251 bool operator!=(const RefPtr<O>& other) const 252 { 253 return !operator==(other); 254 } 255 256 template<class O> 257 bool operator==(const WeakPtr<O>& weak) const 258 { 259 return weak == *this; 260 } 261 template<class O> 262 bool operator!=(const WeakPtr<O>& weak) const 263 { 264 return !operator==(weak); 265 } 266 267 bool operator==(std::nullptr_t) const 268 { 269 return rawPtr_ == nullptr; 270 } 271 bool operator!=(std::nullptr_t) const 272 { 273 return rawPtr_ != nullptr; 274 } 275 276 // Overload '<' is useful for 'std::map', 'std::set' and so on. 277 template<class O> 278 bool operator<(const RefPtr<O>& other) const 279 { 280 if (rawPtr_ == nullptr) { 281 return other.rawPtr_ != nullptr; 282 } 283 return other.rawPtr_ != nullptr && rawPtr_->refCounter_ < other.rawPtr_->refCounter_; 284 } 285 286 private: 287 // Construct instance by raw pointer. 288 // 'WeakPtr' may construct 'RefPtr' without increasing its strong reference count, 289 // because strong reference count is already increased in 'WeakPtr' while upgrading. 290 // In that case, 'forceIncRef' should be 'false'. 291 explicit RefPtr(T* rawPtr, bool forceIncRef = true) : rawPtr_(rawPtr) 292 { 293 if (rawPtr_ != nullptr && forceIncRef) { 294 // Increase strong reference count for holding instance. 295 rawPtr_->IncRefCount(); 296 } 297 } 298 299 friend class Referenced; 300 template<class O> 301 friend class RefPtr; 302 template<class O> 303 friend class WeakPtr; 304 305 T* rawPtr_ { nullptr }; 306 }; 307 308 // Working with 'RefPtr' to resolve 'circular reference'. 309 // Implicit conversion is necessary in some cases, so remove 'explicit' from construct function. 310 template<class T> 311 class WeakPtr final { 312 public: 313 // Basic constructors. 314 WeakPtr() = default; WeakPtr(std::nullptr_t)315 ACE_REMOVE(explicit) WeakPtr(std::nullptr_t) {} 316 // Basic copy and move constructors. WeakPtr(const WeakPtr & other)317 ACE_REMOVE(explicit) WeakPtr(const WeakPtr& other) : WeakPtr(other.unsafeRawPtr_, other.refCounter_) {} WeakPtr(WeakPtr && other)318 ACE_REMOVE(explicit) WeakPtr(WeakPtr&& other) : unsafeRawPtr_(other.unsafeRawPtr_), refCounter_(other.refCounter_) 319 { 320 other.unsafeRawPtr_ = nullptr; 321 other.refCounter_ = nullptr; 322 } 323 // Construct instance by other 'WeakPtr' that inherited from type 'T'. 324 template<class O> ACE_REMOVE(explicit)325 ACE_REMOVE(explicit) WeakPtr(const WeakPtr<O>& other) : WeakPtr(other.unsafeRawPtr_, other.refCounter_) {} 326 template<class O> ACE_REMOVE(explicit)327 ACE_REMOVE(explicit) WeakPtr(WeakPtr<O>&& other) 328 : unsafeRawPtr_(other.unsafeRawPtr_), refCounter_(other.refCounter_) 329 { 330 other.unsafeRawPtr_ = nullptr; 331 other.refCounter_ = nullptr; 332 } 333 // Construct instance by 'RefPtr' that inherited from type 'T' or 'T' itself. 334 template<class O> ACE_REMOVE(explicit)335 ACE_REMOVE(explicit) WeakPtr(const RefPtr<O>& other) : WeakPtr(other.rawPtr_) {} WeakPtr(const RefPtr<T> & other)336 ACE_REMOVE(explicit) WeakPtr(const RefPtr<T>& other) : WeakPtr(other.rawPtr_) {} 337 ~WeakPtr()338 ~WeakPtr() 339 { 340 // Decrease weak reference count while releasing reference counter. 341 if (refCounter_ != nullptr) { 342 refCounter_->DecWeakRef(); 343 refCounter_ = nullptr; 344 unsafeRawPtr_ = nullptr; 345 } 346 } 347 Swap(WeakPtr & other)348 void Swap(WeakPtr& other) 349 { 350 std::swap(unsafeRawPtr_, other.unsafeRawPtr_); 351 std::swap(refCounter_, other.refCounter_); 352 } Swap(WeakPtr && other)353 void Swap(WeakPtr&& other) 354 { 355 Swap(other); 356 } Reset()357 void Reset() 358 { 359 Swap(WeakPtr()); 360 } 361 Upgrade()362 RefPtr<T> Upgrade() const 363 { 364 // A 'WeakPtr' could upgrade to 'RefPtr' if this instance is still alive. 365 return refCounter_ != nullptr && refCounter_->TryIncStrongRef() ? RefPtr<T>(unsafeRawPtr_, false) : nullptr; 366 } Invalid()367 bool Invalid() const 368 { 369 return refCounter_ == nullptr || refCounter_->StrongRefCount() == 0; 370 } 371 372 // Use 'Swap' to implement overloaded operator '=', just like 'RefPtr'. 373 WeakPtr& operator=(const WeakPtr& other) 374 { 375 if (this != &other) { 376 Swap(WeakPtr(other)); 377 } 378 return *this; 379 } 380 WeakPtr& operator=(WeakPtr&& other) 381 { 382 if (this != &other) { 383 Swap(WeakPtr(std::move(other))); 384 } 385 return *this; 386 } 387 388 template<class O> 389 WeakPtr& operator=(O* rawPtr) 390 { 391 Swap(WeakPtr(rawPtr)); 392 return *this; 393 } 394 template<class O> 395 WeakPtr& operator=(const WeakPtr<O>& other) 396 { 397 Swap(WeakPtr(other)); 398 return *this; 399 } 400 template<class O> 401 WeakPtr& operator=(WeakPtr<O>&& other) 402 { 403 Swap(WeakPtr(std::move(other))); 404 return *this; 405 } 406 template<class O> 407 WeakPtr& operator=(const RefPtr<O>& other) 408 { 409 Swap(WeakPtr(other.rawPtr_)); 410 return *this; 411 } 412 413 // Comparing pointer of reference counter to implement Overloaded operator '==' and '!=', just like 'RefPtr'. 414 template<class O> 415 bool operator==(const O* rawPtr) const 416 { 417 if (refCounter_ == nullptr) { 418 return rawPtr == nullptr; 419 } 420 return rawPtr != nullptr && refCounter_ == rawPtr->refCounter_; 421 } 422 template<class O> 423 bool operator!=(const O* rawPtr) const 424 { 425 return !operator==(rawPtr); 426 } 427 428 template<class O> 429 bool operator==(const WeakPtr<O>& other) const 430 { 431 return refCounter_ == other.refCounter_; 432 } 433 template<class O> 434 bool operator!=(const WeakPtr<O>& other) const 435 { 436 return !operator==(other); 437 } 438 439 template<class O> 440 bool operator==(const RefPtr<O>& strong) const 441 { 442 return strong.rawPtr_ != nullptr ? strong.rawPtr_->refCounter_ == refCounter_ : refCounter_ == nullptr; 443 } 444 template<class O> 445 bool operator!=(const RefPtr<O>& strong) const 446 { 447 return !operator==(strong); 448 } 449 450 // Overload '<' is useful for 'std::map', 'std::set' and so on, just like 'RefPtr'. 451 template<class O> 452 bool operator<(const WeakPtr<O>& other) const 453 { 454 return refCounter_ < other.refCounter_; 455 } 456 GetRawPtr()457 inline T* GetRawPtr() const 458 { 459 if (Invalid()) { 460 return nullptr; 461 } 462 return unsafeRawPtr_; 463 } 464 465 private: 466 // Construct instance by raw pointer. WeakPtr(T * rawPtr)467 explicit WeakPtr(T* rawPtr) : WeakPtr(rawPtr, rawPtr != nullptr ? rawPtr->refCounter_ : nullptr) {} 468 template<class O> WeakPtr(O * rawPtr,RefCounter * aceRef)469 WeakPtr(O* rawPtr, RefCounter* aceRef) : unsafeRawPtr_(rawPtr), refCounter_(aceRef) 470 { 471 if (refCounter_) { 472 refCounter_->IncWeakRef(); 473 } 474 } 475 476 friend class Referenced; 477 template<class O> 478 friend class WeakPtr; 479 480 // Notice: Raw pointer of instance is kept, but NEVER use it except succeed to upgrade to 'RefPtr'. 481 T* unsafeRawPtr_ { nullptr }; 482 RefCounter* refCounter_ { nullptr }; 483 }; 484 485 } // namespace OHOS::Ace 486 487 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_REFERENCED_H 488