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 /** 17 * @file refbase.h 18 * 19 * @brief Provide smart pointer implemented in c_utils. 20 */ 21 22 /** 23 * @defgroup SmartPointer 24 * @{ 25 * @brief SmartPointer is a pointer-like class. 26 * 27 * This class simulates a pointer while providing 28 * enhanced features, such as automatic memory management.\n 29 * Automatic memory management helps to deallocate 30 * memory resources correctly when an object's life time expires. 31 */ 32 33#ifndef UTILS_BASE_REFBASE_H 34#define UTILS_BASE_REFBASE_H 35 36#include <atomic> 37#include <functional> 38#ifdef DEBUG_REFBASE 39#include <mutex> 40#endif 41 42namespace OHOS { 43/** 44 * @ingroup SmartPointer 45 * @brief A value indicates no strong references ever. 46 */ 47#define INITIAL_PRIMARY_VALUE (1 << 28) 48 49class RefBase; 50 51#if ((defined DEBUG_REFBASE) && (!defined PRINT_TRACK_AT_ONCE)) 52class RefTracker; 53#endif 54 55/** 56 * @ingroup SmartPointer 57 * @brief Reference counter class. Such a class records two kinds 58 * of references to the corresponding RefBase object and one kind 59 * of references to the RefCounter object itself. 60 * 61 * There are two different references for a single object.\n 62 * A strong reference holds the reference directly pointing to the object, 63 * and the object should be alive as long as the strong reference exists.\n 64 * A weak reference holds a reference indirectly pointing to the object, 65 * and the object is not always alive/existent 66 * even if the weak reference exists. 67 * @note The preceding descriptions are valid only when smart pointers 68 * are properly used. 69 */ 70class RefCounter { 71public: 72 /** 73 * @brief Callback function used to destroy the corresponding 74 * RefBase object. 75 */ 76 using RefPtrCallback = std::function<void()>; 77 friend class RefBase; 78 79 RefCounter(); 80 81 explicit RefCounter(RefCounter *counter); 82 83 RefCounter &operator=(const RefCounter &counter); 84 85 virtual ~RefCounter(); 86 87 /** 88 * @brief Sets the callback function. 89 * 90 * @param callback Callback function used to delete 91 * the corresponding RefBase object. 92 */ 93 void SetCallback(const RefPtrCallback& callback); 94 95 /** 96 * @brief Removes the current callback function by setting it to a `nullptr`. 97 */ 98 void RemoveCallback(); 99 100 /** 101 * @brief Gets the count of references to the RefCounter object. 102 * 103 * @return Count of references to the RefCounter object. 104 */ 105 int GetRefCount(); 106 107 /** 108 * @brief Increments the count of references to the RefCounter object by 1. 109 */ 110 void IncRefCount(); 111 112 /** 113 * @brief Decrements the count of references to the RefCounter object by 1. 114 * 115 * Once the count reaches 0 after being decremented, 116 * `delete this` will be called to deallocate this RefCounter object. 117 */ 118 void DecRefCount(); 119 120 /** 121 * @brief Checks if the pointer to the callback function is a `nullptr`. 122 * 123 * @return `true` if the callback function is a `nullptr`; 124 * `false` otherwise. 125 */ 126 bool IsRefPtrValid(); 127 128 /** 129 * @brief Increments the count of strong references to the 130 * corresponding RefBase object by 1. 131 * 132 * @return Original count before increment. 133 */ 134 int IncStrongRefCount(const void *objectId); 135 136 /** 137 * @brief Decrements the count of strong references to the 138 * corresponding RefBase object by 1. 139 * 140 * @return Original count before decrement. 141 * @note If the strong reference never exists, 142 * decrement will be ineffective. 143 */ 144 int DecStrongRefCount(const void *objectId); 145 146 /** 147 * @brief Gets the count of strong references to the 148 * corresponding RefBase object. 149 * 150 * @return Count of strong references. 151 */ 152 int GetStrongRefCount(); 153 154 /** 155 * @brief Increments the count weak references to the 156 * corresponding RefBase object by 1. 157 * 158 * @return Original count before increment. 159 */ 160 int IncWeakRefCount(const void *objectId); 161 162 /** 163 * @brief Decrements the count of weak references to the 164 * corresponding RefBase object by 1. 165 * 166 * @return Original (before decrement) value of atomicWeak_. 167 * @note If the count reaches 0 after being decremented, the 168 * corresponding RefBase object with no strong reference ever, 169 * or the RefBase object with 0 strong reference but an extended 170 * 'life time', will be deallocated. 171 */ 172 int DecWeakRefCount(const void *objectId); 173 174 /** 175 * @brief Gets the count of weak references to the 176 * corresponding RefBase object. 177 * 178 * @return Count of weak references. 179 */ 180 int GetWeakRefCount(); 181 182 /** 183 * @brief Sets the number of attempts to increment. 184 */ 185 void SetAttemptAcquire(); 186 187 /** 188 * @brief Get the current times of attempts,this interface is only for IPC use. 189 */ 190 int GetAttemptAcquire(); 191 192 /** 193 * @brief Check if the number of attempts is greater than 0. 194 * 195 * @return `true` if the number of attempts is greater than 0; 196 * `false` otherwise. 197 */ 198 bool IsAttemptAcquireSet(); 199 200 /** 201 * @brief Clears number of attempts to increment. 202 */ 203 void ClearAttemptAcquire(); 204 205 /** 206 * @brief Attempts to increment the count of strong references to the 207 * corresponding RefBase object by 1. 208 * 209 * @param outCount If the attempt success, the original value 210 * (before increment) of the count will be stored here. 211 * @return `true` if the attempt is successful; `false` otherwise. 212 */ 213 bool AttemptIncStrongRef(const void *objectId, int &outCount); 214 215 // Only for IPC use. 216 /** 217 * @brief Attempts to increment the count of strong references to the 218 * the corresponding RefBase object by 1 (simplified). 219 * 220 * @return `true` if the attempt is successful; `false` otherwise. 221 * @note Only for IPC use. 222 */ 223 bool AttemptIncStrong(const void *objectId); 224 225 /** 226 * @brief Checks if the corresponding RefBase object 227 * has an extended life-time. 228 * 229 * @return `true` if success; `false` otherwise. 230 */ 231 bool IsLifeTimeExtended(); 232 233 /** 234 * @brief Extends the life-time of corresponding RefBase object. 235 * 236 * This allows the corresponding object keep alive 237 * even if there is no strong reference. 238 * @note The RefBase object will be deallocated 239 * if the count of weak references also reaches 0. 240 */ 241 void ExtendObjectLifetime(); 242 243#ifndef EMULATOR_PLATFORM 244 using CanPromote = std::function<bool()>; 245 246 void SetCanPromote(const CanPromote& canPromote); 247 248 void RemoveCanPromote(); 249 250 bool IsCanPromoteValid(); 251#endif 252 253#if ((defined DEBUG_REFBASE) && (!defined TRACK_ALL)) 254 /** 255 * @brief Enables tracking. It is applicable to debugging only. 256 */ 257 void EnableTracker(); 258#endif 259 260private: 261 void DebugRefBase(const void *objectId); 262 263 std::atomic<int> atomicStrong_; // = (num of sptr) or Initial-value 264 std::atomic<int> atomicWeak_; // = (num of sptr)+(num of WeakRefCounter) 265 std::atomic<int> atomicRefCount_; // = (num of WeakRefCounter) + 1 266 std::atomic<unsigned int> atomicFlags_; // Life-time extended flag 267 std::atomic<int> atomicAttempt_; // Number of attempts 268 RefPtrCallback callback_ = nullptr; // Callback function to deallocate the corresponding RefBase object 269 static constexpr unsigned int FLAG_EXTEND_LIFE_TIME = 0x00000002; // Extended life-time bit to be set via logic-OR 270#ifndef EMULATOR_PLATFORM 271 CanPromote canPromote_ = nullptr; 272#endif 273#ifdef DEBUG_REFBASE 274#ifdef TRACK_ALL 275 bool enableTrack = true; 276#else 277 bool enableTrack = false; 278#endif 279 std::mutex trackerMutex; // To ensure refTracker be thread-safe 280#ifdef PRINT_TRACK_AT_ONCE 281 void PrintRefs(const void* objectId); 282#else 283 RefTracker* refTracker = nullptr; 284 void GetNewTrace(const void* objectId); 285 void PrintTracker(); 286#endif 287#endif 288}; 289 290/** 291 * @ingroup SmartPointer 292 * @brief An intermediate class to represent the weak reference 293 * to the correspond RefBase object. 294 * 295 * A WeakRefCounter object can be shared by multiple wptr objects.\n 296 * It holds the references to the corresponding RefBase and RefCounter object. 297 * Those two references will be set as `nullptr` when the weak referenced 298 * target and its RefCounter object are deallocated. The WeakRefCounter 299 * object can remain alive even if the referenced target is deallocated. 300 */ 301class WeakRefCounter { 302public: 303 /** 304 * @brief Constructs a WeakRefCounter object. 305 * 306 * @param counter Pointer to corresponding RefCounter object. 307 * @param cookie Pointer to corresponding RefBase object. 308 */ 309 WeakRefCounter(RefCounter *counter, void *cookie); 310 311 virtual ~WeakRefCounter(); 312 313 /** 314 * @brief Gets the current pointer to the corresponding RefBase object. 315 * 316 * @return A void pointer to the RefBase object. 317 * If the corresponding object is not alive, a `nullptr` will be returned. 318 * @note A void pointer means that you should cast it to the real type, 319 * since it can be any subclass of RefBase. 320 */ 321 void *GetRefPtr(); 322 323 /** 324 * @brief Increments the count of references to this WeakRefCounter object. 325 * 326 * @note This count is different from the count of weak references 327 * in RefCounter. It is equal to the count of wptrs directly 328 * referenced to this WeakRefCount object. 329 * @see RefCounter 330 */ 331 void IncWeakRefCount(const void *objectId); 332 333 /** 334 * @brief Decrements the count of references to this WeakRefCounter object. 335 * 336 * @note This WeakRefCounter object will be deallocated when this count 337 * reaches 0. 338 */ 339 void DecWeakRefCount(const void *objectId); 340 341 /** 342 * @brief Gets the count recorded by this WeakRefCounter object. 343 * 344 * @return Count recorded by this WeakRefCounter object. 345 * @note The count is different from that in RefCounter. 346 * @see RefCounter::GetWeakRefCount() 347 */ 348 int GetWeakRefCount() const; 349 350 /** 351 * @brief Attempts to increment the count of strong references to 352 * the corresponding RefBase object (to promote a wptr to a sptr). 353 * 354 * @return `true` after a success increment. 355 */ 356 bool AttemptIncStrongRef(const void *objectId); 357 358private: 359 std::atomic<int> atomicWeak_; // Count of references to this 360 // WeakRefCounter object 361 // The value is equal to the count of wptrs 362 // that references this WeakRefCounter object. 363 RefCounter *refCounter_ = nullptr; // Reference to the RefCounter object of 364 // the corresponding RefBase object 365 void *cookie_ = nullptr; // Pointer to the corresponding RefBase object 366}; 367 368/** 369 * @ingroup SmartPointer 370 * @brief A base class of subclasses that can be managed by SmartPointer. 371 * 372 * @note All classes which intend to be managed by SmartPointer should be 373 * derived from RefBase. 374 */ 375class RefBase { 376public: 377 RefBase(); 378 379 /** 380 * @brief Copy constructor of RefBase. 381 * 382 * @note This function constructs a new RefCounter object 383 * and binds it to the RefBase object. 384 */ 385 RefBase(const RefBase &); 386 387 /** 388 * @brief Copy assignment operator of RefBase. 389 * 390 * @note This function unbinds this RefBase object from the 391 * original RefCounter object, and then binds it to the 392 * newly constructed RefCounter object. 393 */ 394 RefBase &operator=(const RefBase &); 395 396 /** 397 * @brief Move constructor of RefBase. 398 */ 399 RefBase(RefBase &&other) noexcept; 400 401 /** 402 * @brief Move assignment operator of RefBase. 403 * 404 * @note This function binds this RefBase object with the RefCounter 405 * object of the argument `other`, which will unbind the 406 * RefCounter object. No counts operation will be processed. 407 */ 408 RefBase &operator=(RefBase &&other) noexcept; 409 410 virtual ~RefBase(); 411 412 /** 413 * @brief Callback function to deallocate this object. 414 * 415 * This function provides the default implementation to deallocate 416 * this RefBase object by simply calling `delete(this)`. 417 */ 418 virtual void RefPtrCallback(); 419 420 /** 421 * @brief Extends the life time of the RefBase object. 422 * 423 * @note The object whose life time has been extended will not be 424 * deallocated if the count of weak references, instead of strong 425 * references, reaches 0. 426 */ 427 void ExtendObjectLifetime(); 428 429 /** 430 * @brief Increments the count of strong references. 431 * 432 * `OnFirstStrongRef()`, which is an empty function by default, 433 * will be called when the first strong reference is established. 434 * 435 * @note This function automatically increments the count of weak 436 * references meanwhile. 437 */ 438 void IncStrongRef(const void *objectId); 439 440 /** 441 * @brief Decrements the count of strong references. 442 * 443 * If the life time is not extended, this object will be deallocated 444 * when the count of strong references reaches 0.\n 445 * `OnLastStrongRef()`, which is an empty function by default, 446 * will be called when the last strong reference is deleted. 447 */ 448 void DecStrongRef(const void *objectId); 449 450 /** 451 * @brief Gets the count of strong references. 452 * 453 * @return Count of strong references. The value is 0 if the 454 * corresponding RefCounter object does not exist. 455 * @note This function is valid only when corresponding RefCounter 456 * object exists. 457 */ 458 int GetSptrRefCount(); 459 460 /** 461 * @brief Creates a weak reference to this RefBase object. 462 * 463 * @param cookie Void pointer to this RefBase object. 464 * @return Pointer to the newly created WeakRefCounter object. 465 * @note Use this function with related functions of wptr. 466 * Do not use it independently. 467 */ 468 WeakRefCounter *CreateWeakRef(void *cookie); 469 470 /** 471 * @brief Gets the pointer to corresponding counter object. 472 * 473 * @return Pointer to the counter object. 474 */ 475 RefCounter *GetRefCounter() const; 476 477 /** 478 * @brief Increments the count of weak references. 479 * 480 * @note This function is valid only when corresponding RefCounter 481 * object exists. 482 */ 483 void IncWeakRef(const void *objectId); 484 485 /** 486 * @brief Decrements the count of weak references. 487 * 488 * @note This function is valid only when corresponding RefCounter 489 * object exists. 490 */ 491 void DecWeakRef(const void *objectId); 492 493 /** 494 * @brief Gets the count of weak references. 495 * 496 * @return Count of weak references. The value is 0 if the corresponding 497 * RefCounter object does not exist. 498 */ 499 int GetWptrRefCount(); 500 501 /** 502 * @brief Attempts to increment the count of strong references. 503 * 504 * `OnFirstStrongRef()`, which is an empty function by default, will be 505 * called when the first strong reference is established. 506 * 507 * @return `true` if the increment is successful; `false` otherwise. 508 * @note The count of attempts will increment by 1 509 * after a successful increment. 510 */ 511 bool AttemptAcquire(const void *objectId); 512 513 /** 514 * @brief Check attempt acquire is setted,this interface is only for IPC use. 515 * This interface must come after the RefBase::AttemptIncStrong or RefBase::AttemptAcquire function, 516 * And ensuring thread safety in multi-threaded scenarios. 517 * 518 * @note This fuction is extracted from `IncStrongRef()` 519 * It is only for IPC use. 520 */ 521 void CheckIsAttemptAcquireSet(const void *objectId); 522 523 /** 524 * @brief Attempts to increment the count of strong references. 525 * 526 * `OnFirstStrongRef()`, which is an empty function by default, will be 527 * called when the first strong reference is established. 528 * @return `true` if the increment is successful; `false` otherwise. 529 * @note Use this function in the copy constructor of sptr in scenario of 530 * interaction between sptr and wptr. Avoid using it independently. 531 */ 532 bool AttemptIncStrongRef(const void *objectId); 533 534 // Only for IPC use. 535 /** 536 * @brief Attempts to increment the count of strong references. 537 * 538 * @return `true` if the increment is successful; `false` otherwise. 539 * @note If the operation is successful, the count of successful attempts 540 * will increment by 1. 541 * @note This function is a simplified version of `AttemptAcquire`. 542 * It is only for IPC use. 543 */ 544 bool AttemptIncStrong(const void *objectId); 545 546 /** 547 * @brief Checks if the count of successful attempts is greater than 0. 548 * 549 * @return `true` if the count of successful attempts is greater than 0; 550 * `false` if the count of successful attempts is not greater than 0 551 * or the corresponding RefCounter object does not exist. 552 */ 553 bool IsAttemptAcquireSet(); 554 555 /** 556 * @brief Checks if the life time of this RefBase object has been extended. 557 * 558 * @return `true` if the life time of this RefBase object has been extended; 559 * `false` if the RefBase object has a normal life time or the corresponding 560 * RefCounter object does not exist. 561 */ 562 bool IsExtendLifeTimeSet(); 563 564 /** 565 * @brief Called when the first strong reference is established. 566 * 567 * @note It is an empty function by default. 568 */ 569 virtual void OnFirstStrongRef(const void *); 570 571 /** 572 * @brief Called when the last strong reference is deleted. 573 * 574 * @note It is an empty function by default. 575 */ 576 virtual void OnLastStrongRef(const void *); 577 578 /** 579 * @brief Called when the last weak reference is deleted. 580 * 581 * @note It is an empty function by default. 582 */ 583 virtual void OnLastWeakRef(const void *); 584 585 /** 586 * @brief Called when `wptr::Promote()` is invoked. 587 * 588 * @return `true` if success; `false` otherwise. 589 */ 590 virtual bool OnAttemptPromoted(const void *); 591 592 /** 593 * @brief Enables tracking of the RefBase object. This function will 594 * be implemented only if DEBUG_REFBASE, but not TRACK_ALL, is defined. 595 */ 596 void EnableTracker(); 597 598#ifndef EMULATOR_PLATFORM 599 virtual bool CanPromote(); 600#endif 601 602private: 603 RefCounter *refs_ = nullptr; // Pointer to the corresponding reference 604 // counter of this RefBase object 605}; 606 607template <typename T> 608class wptr; 609 610/** 611 * @ingroup SmartPointer 612 * @brief Strong reference smart pointer to a RefBase object 613 * (or an object of its subclass). 614 * 615 * It directly reference the RefBase object. 616 * 617 * @tparam T Specific class type managed by sptr. 618 * This class must inherit from RefBase. 619 */ 620template <typename T> 621class sptr { 622 friend class wptr<T>; 623 624public: 625 sptr(); 626 627 ~sptr(); 628 629 /** 630 * @brief Create a new object with class type (T) and provide a new sptr to manage it. 631 * 632 * @note We strongly recommend using `sptr::MakeSptr` to create a object and manage it. 633 * This approach avoids object pointer leaks, which can avoid many potential memory problems. 634 * 635 * @return A sptr which manage a new object with class type (T). 636 * @param args Constructor parameters of the new object to be managed by sptr. 637 */ 638 template <typename... Args> 639 static inline sptr<T> MakeSptr(Args&&... args); 640 641 /** 642 * @brief Constructor with the specified object to be managed. 643 * And We do not recommend using this interface to create an sptr object. 644 * Using the interface `sptr::MakeSptr` is better 645 * 646 * @note A null sptr will be created if `other` is `nullptr`. 647 * @param other Object to be managed by sptr. 648 */ 649 sptr(T *other); 650 651 /** 652 * @brief Copy constructor for sptr with the managed class type (T). 653 * 654 * @param other Input sptr object. 655 */ 656 sptr(const sptr<T> &other); 657 658 /** 659 * @brief Move constructor. 660 * 661 * @note `other` will be set to a null sptr. 662 * @param other Input sptr object. 663 */ 664 sptr(sptr<T> &&other); 665 666 /** 667 * @brief Move assignment operator. 668 * 669 * @param other Input sptr object. 670 * @note The original strong reference in target sptr object will 671 * be removed. 672 */ 673 sptr<T> &operator=(sptr<T> &&other); 674 675 /** 676 * @brief Copy Constructor for sptr with the managed class type (O). 677 * 678 * @tparam O Another specific class type managed by `other`. 679 * @param other Input sptr object. 680 */ 681 template <typename O> 682 sptr(const sptr<O> &other); 683 684 /** 685 * @brief Constructor used to promote the process of wptr. 686 * 687 * @param p WeakRefCounter object which hold the reference to the 688 * managed object. 689 * @param force Used to distinguish from other constructors. 690 */ 691 inline sptr(WeakRefCounter *p, bool force); 692 693 /** 694 * @brief Gets the pointer to the managed object. 695 * 696 * @return Pointer of the specific managed class type. 697 */ 698 inline T *GetRefPtr() const 699 { 700 return refs_; 701 } 702 703 /** 704 * @brief Sets the pointer to the managed object. 705 * 706 * @param other Another pointer object to be managed by sptr. 707 * @note Avoid using this function independently. Otherwise, 708 * a mismatch of the reference count will arise, leading to memory problems. 709 */ 710 inline void ForceSetRefPtr(T *other); 711 712 /** 713 * @brief Removes the reference to the managed object held by current sptr. 714 * 715 * @note This function will make this sptr a "null sptr". 716 */ 717 void clear(); 718 719 /** 720 * @brief Type conversion operator. 721 * 722 * @return Raw pointer to the managed object. 723 * @note The sptr object will not be converted. Only the member raw 724 * pointer will be returned. 725 */ 726 inline operator T *() const 727 { 728 return refs_; 729 } 730 731 /** 732 * @brief Explicit boolean conversion operator. 733 * 734 * @return `true` if refbase object is not a "null ptr"; `false` otherwise. 735 */ 736 inline explicit operator bool() const 737 { 738 return refs_ != nullptr; 739 } 740 741 /** 742 * @brief Dereference operator. 743 * 744 * This function will return the object managed by this sptr. 745 * 746 * @return Reference to the specific object managed by sptr. 747 */ 748 inline T &operator*() const 749 { 750 return *refs_; 751 } 752 753 /** 754 * @brief Member selection operator. 755 * 756 * This function will return the specified member of the object 757 * managed by this sptr. 758 */ 759 inline T *operator->() const 760 { 761 return refs_; 762 } 763 764 /** 765 * @brief Copy assignment operator with the specified object to be managed. 766 * And We do not recommend using this interface to create an sptr object. 767 * Using the interface `sptr::MakeSptr` is better. 768 * 769 * @note The original reference will be removed, and a new reference to the 770 * input object will be established. 771 * @param other Another object to be managed by this sptr. 772 */ 773 sptr<T> &operator=(T *other); 774 775 /** 776 * @brief Copy assignment operator for sptr with 777 * the same managed class type (T). 778 * 779 * @note The original reference will be removed, and the same object 780 * with the input sptr object will be managed by this sptr. 781 * @param other Another sptr object with the same managed class type (T). 782 */ 783 sptr<T> &operator=(const sptr<T> &other); 784 785 /** 786 * @brief Copy assignment operator for wptr with 787 * the same managed class type (T). 788 * 789 * @note The original reference will be removed, and the same object 790 * with the input wptr object will be managed by this sptr. 791 * @note If the operation fails, this sptr will turn to be a "null sptr". 792 * @param other Another wptr object with the same managed class type (T). 793 */ 794 sptr<T> &operator=(const wptr<T> &other); 795 796 /** 797 * @brief Copy assignment operator for sptr with 798 * a different managed class type (O). 799 * 800 * @note The original reference will be removed, and the same object 801 * with the input sptr object will be managed by this sptr. 802 * @note This sptr will interpret the managed object as the type (T). 803 * @param other Another sptr object with a different managed class type (O). 804 */ 805 template <typename O> 806 sptr<T> &operator=(const sptr<O> &other); 807 808 /** 809 * @brief Equal-to operator between the sptr and raw pointer. 810 * 811 * @param other Input raw pointer. 812 * @return `true` if the sptr points to the same object with input 813 * raw pointer; `false` otherwise. 814 */ 815 bool operator==(const T *other) const; 816 817 /** 818 * @brief Not-equal-to operator between the sptr and raw pointer. 819 * 820 * @param other Input raw pointer. 821 * @return `true` if the sptr does not point to the same object 822 * with input raw pointer; `false` otherwise. 823 */ 824 inline bool operator!=(const T *other) const 825 { 826 return !operator==(other); 827 } 828 829 /** 830 * @brief Equal-to operator between the sptr and wptr. 831 * 832 * @param other Input wptr. 833 * @return `true` if the same object is managed by the sptr and wptr; 834 * `false` otherwise. 835 */ 836 bool operator==(const wptr<T> &other) const; 837 838 /** 839 * @brief Not-equal-to operator between the sptr and wptr. 840 * 841 * @param other Input wptr. 842 * @return `true` if different objects are managed by the sptr and wptr; 843 * `false` otherwise. 844 */ 845 inline bool operator!=(const wptr<T> &other) const 846 { 847 return !operator==(other); 848 } 849 850 /** 851 * @brief Equal-to operator between two sptrs. 852 * 853 * @param other Input sptr. 854 * @return `true` if the same object is managed by two sptrs; 855 * `false` otherwise. 856 */ 857 bool operator==(const sptr<T> &other) const; 858 859 /** 860 * @brief Not-equal-to operator between sptrs. 861 * 862 * @param other Input sptr. 863 * @return `true` if different objects are managed by two sptrs; 864 * `false` otherwise. 865 */ 866 inline bool operator!=(const sptr<T> &other) const 867 { 868 return !operator==(other); 869 } 870 871private: 872 T *refs_ = nullptr; // Raw pointer to the specific managed object 873}; 874 875template <typename T> 876template <typename... Args> 877sptr<T> sptr<T>::MakeSptr(Args&&... args) 878{ 879 T *ptr = new T(std::forward<Args>(args)...); 880 sptr<T> res; 881 res.ForceSetRefPtr(ptr); 882 ptr->IncStrongRef(ptr); 883 return res; 884} 885 886template <typename T> 887inline void sptr<T>::ForceSetRefPtr(T *other) 888{ 889 refs_ = other; 890} 891 892template <typename T> 893inline sptr<T>::sptr() 894{ 895 refs_ = nullptr; 896} 897 898template <typename T> 899inline sptr<T>::sptr(T *other) 900{ 901 refs_ = other; 902 if (refs_ != nullptr) { 903 refs_->IncStrongRef(this); 904 } 905} 906 907template <typename T> 908inline sptr<T>::sptr(const sptr<T> &other) 909{ 910 refs_ = other.GetRefPtr(); 911 if (refs_ != nullptr) { 912 refs_->IncStrongRef(this); 913 } 914} 915 916template <typename T> 917sptr<T>::sptr(sptr<T> &&other) 918{ 919 refs_ = other.GetRefPtr(); 920 other.ForceSetRefPtr(nullptr); 921} 922 923template <typename T> 924sptr<T> &sptr<T>::operator=(sptr<T> &&other) 925{ 926 if (refs_ != nullptr) { 927 refs_->DecStrongRef(this); 928 } 929 refs_ = other.GetRefPtr(); 930 other.ForceSetRefPtr(nullptr); 931 return *this; 932} 933 934template <typename T> 935template <typename O> 936sptr<T>::sptr(const sptr<O> &other) : refs_(other.GetRefPtr()) 937{ 938 if (refs_ != nullptr) { 939 refs_->IncStrongRef(this); 940 } 941} 942 943template <typename T> 944inline sptr<T> &sptr<T>::operator=(T *other) 945{ 946 if (other != nullptr) { 947 other->IncStrongRef(this); 948 } 949 950 if (refs_ != nullptr) { 951 refs_->DecStrongRef(this); 952 } 953 954 refs_ = other; 955 return *this; 956} 957 958template <typename T> 959inline sptr<T> &sptr<T>::operator=(const sptr<T> &other) 960{ 961 T *otherRef(other.GetRefPtr()); 962 if (otherRef != nullptr) { 963 otherRef->IncStrongRef(this); 964 } 965 966 if (refs_ != nullptr) { 967 refs_->DecStrongRef(this); 968 } 969 970 refs_ = otherRef; 971 return *this; 972} 973 974template <typename T> 975inline sptr<T> &sptr<T>::operator=(const wptr<T> &other) 976{ 977 if (refs_ != nullptr) { 978 refs_->DecStrongRef(this); 979 } 980 if ((other != nullptr) && other.AttemptIncStrongRef(this)) { 981 refs_ = other.GetRefPtr(); 982 } else { 983 refs_ = nullptr; 984 } 985 986 return *this; 987} 988 989template <typename T> 990template <typename O> 991sptr<T> &sptr<T>::operator=(const sptr<O> &other) 992{ 993 T *otherRef(other.GetRefPtr()); 994 if (otherRef != nullptr) { 995 otherRef->IncStrongRef(this); 996 } 997 998 if (refs_ != nullptr) { 999 refs_->DecStrongRef(this); 1000 } 1001 1002 refs_ = otherRef; 1003 return *this; 1004} 1005 1006template <typename T> 1007inline bool sptr<T>::operator==(const T *other) const 1008{ 1009 return other == refs_; 1010} 1011 1012template <typename T> 1013inline bool sptr<T>::operator==(const wptr<T> &other) const 1014{ 1015 return refs_ == other.GetRefPtr(); 1016} 1017 1018template <typename T> 1019inline bool sptr<T>::operator==(const sptr<T> &other) const 1020{ 1021 return refs_ == other.GetRefPtr(); 1022} 1023 1024template<typename T> 1025void sptr<T>::clear() 1026{ 1027 if (refs_) { 1028 refs_->DecStrongRef(this); 1029 refs_ = 0; 1030 } 1031} 1032 1033template <typename T> 1034inline sptr<T>::~sptr() 1035{ 1036 if (refs_ != nullptr) { 1037 refs_->DecStrongRef(this); 1038 } 1039} 1040 1041template <typename T> 1042inline sptr<T>::sptr(WeakRefCounter *p, bool /* force */) 1043{ 1044 if ((p != nullptr) && p->AttemptIncStrongRef(this)) { 1045 refs_ = reinterpret_cast<T *>(p->GetRefPtr()); 1046 } else { 1047 refs_ = nullptr; 1048 } 1049} 1050 1051/** 1052 * @ingroup SmartPointer 1053 * @brief Weak reference smart pointer to a RefBase object 1054 * (or an object of its subclass). 1055 * 1056 * A weak reference indirectly references the RefBase object 1057 * and directly references the WeakRefCounter object. 1058 * 1059 * @tparam T Specific class type managed by wptr. 1060 * This class must inherit from RefBase. 1061 */ 1062template <typename T> 1063class wptr { 1064 template <typename O> 1065 friend class wptr; 1066 1067public: 1068 wptr(); 1069 1070 /** 1071 * @brief Constructor with the specified object to be managed. 1072 * 1073 * This function will create WeakRefCounter object for `other` 1074 * and set the count of weak references to 1. 1075 * 1076 * @note A WeakRefCounter object will not be created if `other` 1077 * is a `nullptr`. 1078 * 1079 * @param other Object to be managed by wptr. 1080 */ 1081 wptr(T *other); 1082 1083 /** 1084 * @brief Copy constructor for wptr with the same managed class type (T). 1085 * 1086 * This function will share the WeakRefCounter object of `other` with this 1087 * wptr and set the count of weak references properly. 1088 * 1089 * @param other Another wptr with the same managed class type (T). 1090 */ 1091 wptr(const wptr<T> &other); 1092 1093 /** 1094 * @brief Copy constructor for sptr with the same managed class type (T). 1095 * 1096 * This function will create a WeakRefCounter object for the managed 1097 * object of `other`, and set the count of weak references properly. 1098 * 1099 * @param other Another sptr with the same managed class type (T). 1100 * @tparam T Specific class type managed by `other`. 1101 */ 1102 wptr(const sptr<T> &other); 1103 1104 /** 1105 * @brief Copy constructor for wptr with a different managed class type (O). 1106 * 1107 * This function is the same as wptr<T>::wptr(const wptr<T> &other). 1108 * 1109 * @tparam O Class type managed by `other`. 1110 * @param other Another wptr with a different managed class type (O). 1111 * @tparam T Specific class type managed by `other`. 1112 */ 1113 template <typename O> 1114 wptr(const wptr<O> &other); 1115 1116 /** 1117 * @brief Copy constructor for sptr with a different managed class type (O). 1118 * 1119 * This function is the same as wptr<T>::wptr(const sptr<T> &other). 1120 * 1121 * @param other Another sptr with the same managed class type (O). 1122 * @tparam T Specific class type managed by `other`. 1123 */ 1124 template <typename O> 1125 wptr(const sptr<O> &other); 1126 1127 /** 1128 * @brief Copy assignment operator with the specified object to be managed. 1129 * 1130 * @note The current wptr will unbind the original WeakRefCounter object, 1131 * create a new WeakRefCounter object, and then set the count of weak 1132 * references properly. 1133 * @param other Another object to be managed by this wptr. 1134 */ 1135 wptr<T> &operator=(T *other); 1136 1137 /** 1138 * @brief Copy assignment operator with the specified object to be managed. 1139 * 1140 * @note Same with wptr<T> &operator=(T *other), but a pointer type casting 1141 * which will not affect the type of `*other` is processed. 1142 * @tparam O Specific class type managed by `other`. 1143 * @param other Another object to be managed by this wptr. 1144 * 1145 */ 1146 template <typename O> 1147 wptr<T> &operator=(O *other); 1148 1149 /** 1150 * @brief Copy assignment operator for wptr with the same managed class 1151 * type (T). 1152 * 1153 * @note The current wptr will unbind the original WeakRefCounter object, 1154 * share the WeakRefCounter object with `other`, and then set the count of 1155 * weak references properly. 1156 * @param other Another wptr object. Objects managed by it will also be 1157 * managed by this wptr. 1158 */ 1159 wptr<T> &operator=(const wptr<T> &other); 1160 1161 /** 1162 * @brief Copy assignment operator for sptr with the same managed class 1163 * type (T). 1164 * 1165 * @note The current wptr will unbind the original WeakRefCounter object, 1166 * create a new WeakRefCounter object, and then set the count of weak 1167 * references properly. 1168 * @param other A sptr object. Objects managed by it will also be 1169 * managed by this wptr. 1170 */ 1171 wptr<T> &operator=(const sptr<T> &other); 1172 1173 /** 1174 * @brief Copy assignment operator for wptr with a different managed class 1175 * type (O). 1176 * 1177 * @note This function is the same as wptr<T> &operator=(const wptr<T> &). 1178 * Note that no cast here is processed. 1179 * @param other An wptr object. Objects managed by it will also be 1180 * managed by this wptr. 1181 * @tparam O Specific class type managed by `other`. 1182 */ 1183 template <typename O> 1184 wptr<T> &operator=(const wptr<O> &other); 1185 1186 /** 1187 * @brief Copy assignment operator for sptr with a different managed class 1188 * type (O). 1189 * 1190 * @note This function is the same as 1191 * wptr<T> &wptr<T>::operator=(const sptr<T> &). 1192 * Note that no cast here is processed. 1193 * @param other An sptr object. Objects managed by it will also be 1194 * managed by this wptr. 1195 * @tparam O Specific class type managed by `other`. 1196 */ 1197 template <typename O> 1198 wptr<T> &operator=(const sptr<O> &other); 1199 1200 /** 1201 * @brief Dereference operator. 1202 * 1203 * This function will return the object managed by this wptr. 1204 * 1205 * @return Specific object managed by wptr. 1206 */ 1207 inline T &operator*() const 1208 { 1209 return *GetRefPtr(); 1210 } 1211 1212 /** 1213 * @brief Member selection operator. 1214 * 1215 * This function will return the specified object member managed 1216 * by this wptr. 1217 */ 1218 inline T *operator->() const 1219 { 1220 return reinterpret_cast<T *>(refs_->GetRefPtr()); 1221 } 1222 1223 /** 1224 * @brief Equal-to operator between the wptr and raw pointer. 1225 * 1226 * @param other Input raw pointer. 1227 * @return `true` if two pointers have the same value; `false` otherwise. 1228 */ 1229 bool operator==(const T *other) const; 1230 1231 /** 1232 * @brief Not-equal-to operator between the wptr and raw pointer. 1233 * 1234 * @param other Input raw pointer. 1235 * @return `true` if two pointers have different values; `false` otherwise. 1236 */ 1237 inline bool operator!=(const T *other) const 1238 { 1239 return !operator==(other); 1240 }; 1241 1242 /** 1243 * @brief Equal-to operator between two wptrs. 1244 * 1245 * @param other Input reference to a wptr object. 1246 * @return `true` if two pointers have the same value; `false` otherwise. 1247 */ 1248 bool operator==(const wptr<T> &other) const; 1249 1250 /** 1251 * @brief Not-equal-to operator between two wptrs. 1252 * 1253 * @param other Input reference to a wptr object. 1254 * @return `true` if two pointers have different values; `false` otherwise. 1255 */ 1256 inline bool operator!=(const wptr<T> &other) const 1257 { 1258 return !operator==(other); 1259 } 1260 1261 /** 1262 * @brief Equal-to operator between the wptr and input sptr object. 1263 * 1264 * @param other Input reference to an sptr object. 1265 * @return true` if two pointers have the same value; `false` otherwise. 1266 */ 1267 bool operator==(const sptr<T> &other) const; 1268 1269 /** 1270 * @brief Not-equal-to operator between the wptr and input sptr object. 1271 * 1272 * @param other Input reference to an sptr object. 1273 * @return `true` if two pointers have different values; `false` otherwise. 1274 */ 1275 inline bool operator!=(const sptr<T> &other) const 1276 { 1277 return !operator==(other); 1278 } 1279 1280 /** 1281 * @brief Gets the pointer to the RefBase object. 1282 * 1283 * @return Raw pointer to the RefBase object. 1284 * @note `nullptr` will be returned if the managed object has been 1285 * deallocated. 1286 */ 1287 T *GetRefPtr() const; 1288 1289 /** 1290 * @brief Gets the count of weak references in a WeakRefCounter object. 1291 * 1292 * The value indicates how many wptrs share the same WeakRefCounter object. 1293 * 1294 * @return Count of weak references. 1295 * @note Only for test. 1296 */ 1297 inline int GetWeakRefCount() const 1298 { 1299 return refs_->GetWeakRefCount(); 1300 } 1301 1302 /** 1303 * @brief Attempts to increment the count of strong references in 1304 * the managed object. 1305 * 1306 * @return `true` if the increment is successful; `false` otherwise. 1307 * @note Avoid using this function independently. Use `promote()` instead. 1308 */ 1309 inline bool AttemptIncStrongRef(const void *objectId) const 1310 { 1311 return refs_->AttemptIncStrongRef(objectId); 1312 } 1313 1314 /** 1315 * @brief Promotes a wptr to an sptr. 1316 * 1317 * This function will create an sptr object based on the object 1318 * managed by this wptr. 1319 * 1320 * @note The original weak reference will be retained. 1321 * If the promotion fails, a "null sptr" will be returned. 1322 */ 1323 const sptr<T> promote() const; 1324 1325 ~wptr(); 1326 1327private: 1328 WeakRefCounter *refs_ = nullptr; // Pointer to the corresponding WeakRefCounter object 1329}; 1330 1331template <typename T> 1332inline T *wptr<T>::GetRefPtr() const 1333{ 1334 return (refs_ != nullptr) ? reinterpret_cast<T *>(refs_->GetRefPtr()) : nullptr; 1335} 1336 1337template <typename T> 1338wptr<T>::wptr() 1339{ 1340 refs_ = nullptr; 1341} 1342 1343template <typename T> 1344wptr<T>::wptr(T *other) 1345{ 1346 if (other != nullptr) { 1347 refs_ = other->CreateWeakRef(other); 1348 if (refs_ != nullptr) { 1349 refs_->IncWeakRefCount(this); 1350 } 1351 } else { 1352 refs_ = nullptr; 1353 } 1354} 1355 1356template <typename T> 1357wptr<T>::wptr(const wptr<T> &other) 1358{ 1359 refs_ = other.refs_; 1360 if (refs_ != nullptr) { 1361 refs_->IncWeakRefCount(this); 1362 } 1363} 1364 1365template <typename T> 1366wptr<T>::wptr(const sptr<T> &other) 1367{ 1368 if (other.GetRefPtr() != nullptr) { 1369 refs_ = other->CreateWeakRef(other.GetRefPtr()); 1370 if (refs_ != nullptr) { 1371 refs_->IncWeakRefCount(this); 1372 } 1373 } 1374} 1375 1376template <typename T> 1377template <typename O> 1378wptr<T>::wptr(const wptr<O> &other) 1379{ 1380 refs_ = other.refs_; 1381 if (refs_ != nullptr) { 1382 refs_->IncWeakRefCount(this); 1383 } 1384} 1385 1386template <typename T> 1387template <typename O> 1388wptr<T>::wptr(const sptr<O> &other) 1389{ 1390 if (other.GetRefPtr() != nullptr) { 1391 refs_ = other->CreateWeakRef(other.GetRefPtr()); 1392 if (refs_ != nullptr) { 1393 refs_->IncWeakRefCount(this); 1394 } 1395 } 1396} 1397 1398template <typename T> 1399wptr<T> &wptr<T>::operator=(T *other) 1400{ 1401 WeakRefCounter *newWeakRef = nullptr; 1402 if (other != nullptr) { 1403 newWeakRef = other->CreateWeakRef(other); 1404 if (newWeakRef != nullptr) { 1405 newWeakRef->IncWeakRefCount(this); 1406 } 1407 } 1408 1409 if (refs_ != nullptr) { 1410 refs_->DecWeakRefCount(this); 1411 } 1412 1413 refs_ = newWeakRef; 1414 return *this; 1415} 1416 1417template <typename T> 1418template <typename O> 1419wptr<T> &wptr<T>::operator=(O *other) 1420{ 1421 T *object = reinterpret_cast<T *>(other); 1422 WeakRefCounter *newWeakRef = nullptr; 1423 if (object != nullptr) { 1424 newWeakRef = object->CreateWeakRef(object); 1425 if (newWeakRef != nullptr) { 1426 newWeakRef->IncWeakRefCount(this); 1427 } 1428 } 1429 1430 if (refs_ != nullptr) { 1431 refs_->DecWeakRefCount(this); 1432 } 1433 1434 refs_ = newWeakRef; 1435 return *this; 1436} 1437 1438template <typename T> 1439inline wptr<T> &wptr<T>::operator=(const wptr<T> &other) 1440{ 1441 if (other.refs_ != nullptr) { 1442 other.refs_->IncWeakRefCount(this); 1443 } 1444 1445 if (refs_ != nullptr) { 1446 refs_->DecWeakRefCount(this); 1447 } 1448 1449 refs_ = other.refs_; 1450 return *this; 1451} 1452 1453template <typename T> 1454inline wptr<T> &wptr<T>::operator=(const sptr<T> &other) 1455{ 1456 WeakRefCounter *newWeakRef = nullptr; 1457 if (other.GetRefPtr() != nullptr) { 1458 newWeakRef = other->CreateWeakRef(other.GetRefPtr()); 1459 if (newWeakRef != nullptr) { 1460 newWeakRef->IncWeakRefCount(this); 1461 } 1462 } 1463 1464 if (refs_ != nullptr) { 1465 refs_->DecWeakRefCount(this); 1466 } 1467 1468 refs_ = newWeakRef; 1469 return *this; 1470} 1471 1472template <typename T> 1473template <typename O> 1474wptr<T> &wptr<T>::operator=(const wptr<O> &other) 1475{ 1476 if (other.refs_ != nullptr) { 1477 other.refs_->IncWeakRefCount(this); 1478 } 1479 1480 if (refs_ != nullptr) { 1481 refs_->DecWeakRefCount(this); 1482 } 1483 1484 refs_ = other.refs_; 1485 return *this; 1486} 1487 1488template <typename T> 1489template <typename O> 1490wptr<T> &wptr<T>::operator=(const sptr<O> &other) 1491{ 1492 WeakRefCounter *newWeakRef = nullptr; 1493 if (other.GetRefPtr() != nullptr) { 1494 newWeakRef = other->CreateWeakRef(other.GetRefPtr()); 1495 if (newWeakRef != nullptr) { 1496 newWeakRef->IncWeakRefCount(this); 1497 } 1498 } 1499 1500 if (refs_ != nullptr) { 1501 refs_->DecWeakRefCount(this); 1502 } 1503 1504 refs_ = newWeakRef; 1505 return *this; 1506} 1507 1508template <typename T> 1509inline bool wptr<T>::operator==(const T *other) const 1510{ 1511 return GetRefPtr() == other; 1512} 1513 1514template <typename T> 1515inline bool wptr<T>::operator==(const wptr<T> &other) const 1516{ 1517 return GetRefPtr() == other.GetRefPtr(); 1518} 1519 1520template <typename T> 1521inline bool wptr<T>::operator==(const sptr<T> &other) const 1522{ 1523 return GetRefPtr() == other.GetRefPtr(); 1524} 1525 1526template <typename T> 1527inline const sptr<T> wptr<T>::promote() const 1528{ 1529 return sptr<T>(refs_, true); 1530} 1531 1532template <typename T> 1533inline wptr<T>::~wptr() 1534{ 1535 if (refs_ != nullptr) { 1536 refs_->DecWeakRefCount(this); 1537 } 1538} 1539 1540} // namespace OHOS 1541 1542#endif 1543 1544/**@}*/ 1545