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