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