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