/* * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file refbase.h * * @brief Provide smart pointer implemented in c_utils. */ /** * @defgroup SmartPointer * @{ * @brief Smart Pointer are pointer-like classes. * * They simulates a pointer while providing added features, * such as automatic memory management.\n * Automatic memory management is mainly about deallocating * the related memory correctly when an object beyonds its life cycle. */ #ifndef UTILS_BASE_REFBASE_H #define UTILS_BASE_REFBASE_H #include #include #ifdef DEBUG_REFBASE #include #endif #ifdef _WIN32 #define RS_EXPORT __attribute__((dllexport)) #else #define RS_EXPORT __attribute__((visibility("default"))) #endif namespace OHOS { /** * @ingroup SmartPointer * @brief A value indicates no strong references exist ever. */ #define INITIAL_PRIMARY_VALUE (1 << 28) class RefBase; #ifdef DEBUG_REFBASE class RefTracker; #endif /** * @ingroup SmartPointer * @brief Reference counter. A class records two kinds of count of references to * the corresponding RefBase object, and a count of references to the RefCounter * itself. * * There are two different references for a single object.\n * Strong Reference holds a reference directly point to the object. * Objects which are strong referenced ought to be alive/existed * as long as this strong reference exists, thus the reference * is still valid.\n * Weak Reference holds a reference indirectly point to the object. * Objects which are weak referenced are not guaranteed to be alive/existed * even if the weak reference exists. * @note Descriptions above are valid only when smart pointers * are properly used. */ class RefCounter { public: /** * @brief Callback function to destroy the corresponding RefBase object. */ using RefPtrCallback = std::function; friend class RefBase; RefCounter(); explicit RefCounter(RefCounter *counter); RefCounter &operator=(const RefCounter &counter); virtual ~RefCounter(); /** * @brief Set the callback function. * * @param callback A function to be set to delete * the corresponding RefBase object. */ void SetCallback(const RefPtrCallback& callback); /** * @brief Remove the current callback function. Set it to a `nullptr`. */ void RemoveCallback(); /** * @brief Get reference count to the RefCounter object. * * @return Value of the related count. */ int GetRefCount(); /** * @brief Increment the reference count to the RefCounter object by 1. */ void IncRefCount(); /** * @brief Decrement the reference count to the RefCounter object by 1. * * Once the count reaches 0 after being decremented, * it will call `delete this` to deallocate this RefCounter object. */ void DecRefCount(); /** * @brief Check if pointer to the call back function is a `nullptr`. * * @return Return true if it is not a `nullptr`. */ bool IsRefPtrValid(); /** * @brief Increment the strong reference count to the * corresponding RefBase object by 1. * * @return Original (before increment) value of the count. */ int IncStrongRefCount(const void *objectId); /** * @brief Decrement the strong reference count to the * corresponding RefBase object by 1. * * @return Original (before decrement) value of the count. * @note If the strong reference has never existed, * decrement will cause no effection. */ int DecStrongRefCount(const void *objectId); /** * @brief Get the strong reference count to the * corresponding RefBase object. * * @return Value of the related count. */ int GetStrongRefCount(); /** * @brief Increment the weak reference count to the * corresponding RefBase object by 1. * * @return Original (before increment) value of the count. */ int IncWeakRefCount(const void *objectId); /** * @brief Decrement the weak reference count to the * corresponding RefBase object by 1. * * @return Original (before decrement) value of atomicWeak_. * @note When the count reaches 0 after being decremented, the * corresponding RefBase object with no strong reference ever, * or the object with strong reference count of 0 but has not been * deallocated due to its extended 'life time', will be deallocated. */ int DecWeakRefCount(const void *objectId); /** * @brief Get the weak reference count to the * corresponding RefBase object. * * @return Value of the related count. */ int GetWeakRefCount(); /** * @brief Increment the times of attempts to increment. */ void SetAttemptAcquire(); /** * @brief Check if the times of attempts greater than 0. * * @return Return true if the times is greater than 0. */ bool IsAttemptAcquireSet(); /** * @brief Clear the times of attempts to increment. */ void ClearAttemptAcquire(); /** * @brief Attempt to increment the strong reference count to the * corresponding RefBase object by 1. * * @param outCount If the attempt success, the original value * (before increment) of the count will be stored here. * @return Return true if the attempt success. */ bool AttemptIncStrongRef(const void *objectId, int &outCount); // Only for IPC use. /** * @brief Attempt to increment the strong reference count to * the corresponding RefBase object by 1(Simplified). * * @return Return true if the attempt success. * @note Ony for IPC use. */ bool AttemptIncStrong(const void *objectId); /** * @brief Check if the corresponding RefBase object * own an extended life-time. * * @return Return true if its life-time has been extended. */ bool IsLifeTimeExtended(); /** * @brief Extend the life-time of corresponding RefBase object. * * It allows the corresponding object keep alive * even if there exists no strong reference to it. * @note Corresponding object will be deallocated * when related weak reference count also reach 0. */ void ExtendObjectLifetime(); #ifndef ROSEN_EMULATOR using CanPromote = std::function; void SetCanPromote(const CanPromote& canPromote); void RemoveCanPromote(); bool IsCanPromoteValid(); #endif private: std::atomic atomicStrong_; // = (num of sptr) or Initial-value std::atomic atomicWeak_; // = (num of sptr)+(num of WeakRefCounter) std::atomic atomicRefCount_; // = (num of WeakRefCounter) + 1 std::atomic atomicFlags_; // A life-time extended flag std::atomic atomicAttempt_; // Times of attempts RefPtrCallback callback_ = nullptr; // A callback function to deallocate the corresponding RefBase object static constexpr unsigned int FLAG_EXTEND_LIFE_TIME = 0x00000002; // Extended life-time bit to be set via logic-OR #ifndef ROSEN_EMULATOR CanPromote canPromote_ = nullptr; #endif #ifdef DEBUG_REFBASE RefTracker* refTracker = nullptr; std::mutex trackerMutex; // To ensure refTracker be thread-safe void GetNewTrace(const void* objectId); void PrintTracker(); #endif }; #ifdef DEBUG_REFBASE // RefTracker is a debug tool, used to record the trace of RefBase. // RefTracker will save the information about the count of RefBase, // including the pointer of sptr/wptr(The pointer of itself, not the pointer // it manages), the amount of strong/weak/refcout and the PID&TID. // The Tracker can live with RefCounter/RefBase(including its derivation). // User should keep thread-safety of RefTracker. class RefTracker { public: RefTracker() {}; RefTracker(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid); void GetTrace(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid); // Only used for tracking the amount of Strong Reference. void GetStrongTrace(RefTracker* exTracker, const void* id, int strong, int pid, int tid); // Only used for tracking the amount of Weak Reference. void GetWeakTrace(RefTracker* exTracker, const void* id, int weak, int pid, int tid); void PrintTrace(const void* root); void PrintStrongTrace(const void* root); void PrintWeakTrace(const void* root); RefTracker* GetexTrace(); RefTracker* PopTrace(const void* root); private: const void* ptrID; int strongRefCNT; int weakRefCNT; int refCNT; int PID; int TID; RefTracker* exTrace; }; #endif /** * @ingroup SmartPointer * @brief An intermediate class to represent the weak reference * to the correspond RefBase object. * * A WeakRefCounter object can be held by multiple wptr objects.\n * It holds references to the corresponding RefBase and RefCounter object. * Those two references will be set as `nullptr`s, when the weak referenced * target and its RefCounter object has been deallocated. Thus WeakRefCounter * object can still alive even if the target refereneced by this object * is vanished. */ class WeakRefCounter { public: /** * @brief Construct a new Weak Ref Counter object. * * @param counter Pointer to corresponding RefCounter object. * @param cookie Pointer to corresponding RefBase object. */ WeakRefCounter(RefCounter *counter, void *cookie); virtual ~WeakRefCounter(); /** * @brief Get current pointer to the corresponding RefBase object. * * @return A void pointer to the RefBase object. * If the corresponding object does not alive, a `nullptr` will return. * @note Void pointer means you should cast it to the real type, since it * can be kinds of subclasses of RefBase. */ void *GetRefPtr(); /** * @brief Increment the reference count to this WeakRefCounter object. * * @note Notice the difference between this count and the weak reference * count in RefCounter. This value equals to the number of wptrs directly * referencing this WeakRefCount object. * @see RefCounter */ void IncWeakRefCount(const void *objectId); /** * @brief Decrement the reference count to this WeakRefCounter object. * * @note This WeakRefCounter object will be deallocated when this count * reaches 0. */ void DecWeakRefCount(const void *objectId); /** * @brief Get the count recorded by this WeakRefCounter object. * * @return Value of the count. * @note This value of count is different from that in RefCounter. * @see RefCounter::GetWeakRefCount() */ int GetWeakRefCount() const; /** * @brief Attempt to increment the strong reference count of * the corresponding RefBase object(Used in promoting a wptr to a sptr). * * @return Return `true` after a success increment. */ bool AttemptIncStrongRef(const void *objectId); private: std::atomic atomicWeak_; // Count of references to this WeakRefCounter object // The value equals to the total amount of wptrs which // reference this WeakRefCounter object RefCounter *refCounter_ = nullptr; // reference to the RefCounter object of corresponding RefBase Object void *cookie_ = nullptr; // Pointer to the corresponding RefBase object }; /** * @ingroup SmartPointer * @brief A base class which can be managed by a smart pointer. * * @note All classes which intend to be managed by smart pointers should be * derived from RefBase. */ class RS_EXPORT RefBase { public: RefBase(); /** * @brief Copy constructor of RefBase. * * @note Note that this method will construct a new RefCounter object, * and bind with it. */ RefBase(const RefBase &); /** * @brief Copy assignment operator of RefBase. * * @note This method will unbind the current RefBase object and its * original RefCounter object, then bind a newly constructed * RefCounter object. */ RefBase &operator=(const RefBase &); /** * @brief Move constructor of RefBase. */ RefBase(RefBase &&other) noexcept; /** * @brief Move assignment operator of RefBase. * * @note This method will bind this RefBase object with the RefCounter * object of the argument `other`, then `other` will unbind the RefCounter * object.\n No counts operation will be poccessed. */ RefBase &operator=(RefBase &&other) noexcept; virtual ~RefBase(); /** * @brief A callback method to deallocate this object. * * This method has default implement to simply deallocate this RefBase * object simply by calling `delete(this)`. */ virtual void RefPtrCallback(); /** * @brief Extend life time of the RefBase object. * * @note The object whose life time has been extended will not be * deallocated when the the weak reference count reach 0 instead of the * strong one. */ void ExtendObjectLifetime(); /** * @brief Increment the strong reference count. * * `OnFirstStrongRef()`, which is an empty method by default, will be * called when the first strong reference are established.、 * * @note It will atomically increment the weak reference count meanwhile. */ void IncStrongRef(const void *objectId); /** * @brief Decrement the strong reference count. * * This object will be deallocated when the count reaches 0, if it owns a * normal life time.\n `OnLastStrongRef()`, which is an empty method by * default, will be called when the last strong reference vanishes. */ void DecStrongRef(const void *objectId); /** * @brief Get the strong reference count. * * @return Related count value. Return 0 when corresponding RefCounter * object does not exist. * @note Only valid when corresponding RefCounter object exists. */ int GetSptrRefCount(); /** * @brief Create weak reference to this RefBase object. * * Create a WeakRefCounter object which holds reference to this RefBase * object and set the reference count. * * @param cookie Void pointer to this RefBase object. * @return Pointer to the newly created WeakRefCounter object. * @note Avoid using it independently. Use related methods of wptr. */ WeakRefCounter *CreateWeakRef(void *cookie); /** * @brief Get the pointer to corresponding counter object. * * @return Pointer to the counter object. */ RefCounter *GetRefCounter() const; /** * @brief Increment the weak reference count. * * @note Only valid when corresponding RefCounter object exists. */ void IncWeakRef(const void *objectId); /** * @brief Decrement the weak reference count. * * @note Only valid when corresponding RefCounter object exists. */ void DecWeakRef(const void *objectId); /** * @brief Get the weak reference count. * * @return Value of related count. Return 0 when corresponding * RefCounter object doesn't exist. */ int GetWptrRefCount(); /** * @brief Attempt to increment the strong reference count. * * `OnFirstStrongRef()`, which is an empty method by default, will be * called when the first strong reference are established. * * @return Return true if successfully increment the count. * @note Note that count of times of attempts will increment by 1 * after a successful increment. */ bool AttemptAcquire(const void *objectId); /** * @brief Attempt to increment the strong reference count. * * `OnFirstStrongRef()`, which is an empty method by default, will be * called when the first strong reference are established. * @return Return true if successfully increment the count. * @note Used in various copy constructor of sptr in scenario of * interaction between sptr and wptr. Avoid using it independently. */ bool AttemptIncStrongRef(const void *objectId); // Only for IPC use. /** * @brief Attempt to increment the strong reference count. * * @return Return true if successfully increment the count, otherwise * return false. * @note Note that times of successful attempts will increment by 1 after * a successful increment of the related count. * @note This method is a simplified version of `AttemptAcquire`, but only * for IPC use. */ bool AttemptIncStrong(const void *objectId); /** * @brief check if the times of successful attempts of greater than 0. * * @return Return true if times of successful attempts is greater than 0; * Return false if it is not greater than 0, or the corresponding * RefCounter object does not exist. */ bool IsAttemptAcquireSet(); /** * @brief Check if the life time of this RefBase object has been extended. * * @return Return false when have a normal life time, or the corresponding * RefCounter object does not exist. */ bool IsExtendLifeTimeSet(); /** * @brief An event-drive method, which will be automatically called when * first strong reference comes up. * * @note It is an empty function by default. */ virtual void OnFirstStrongRef(const void *); /** * @brief An event-drive method, which will be automatically called when * last strong reference eliminates. * * @note It is an empty function by default. */ virtual void OnLastStrongRef(const void *); /** * @brief An event-drive method, which will be automatically called when * last weak reference eliminates. * * @note It is an empty function by default. */ virtual void OnLastWeakRef(const void *); /** * @brief An event-drive method, which will be autmatically called when * use `wptr::Promote()`. * * @note Directly return true by default. * @return Return true if success, otherwise return false. */ virtual bool OnAttemptPromoted(const void *); #ifndef ROSEN_EMULATOR virtual bool CanPromote(); #endif private: RefCounter *refs_ = nullptr; // Pointer to the corresponding reference counter of this RefBase object }; template class wptr; /** * @ingroup SmartPointer * @brief Strong reference smart pointer to a RefBase(or its subclass) object. * * It directly reference the RefBase object. * * @tparam T Specific class type managed by sptr. This class must inherit * from RefBase. */ template class sptr { friend class wptr; public: sptr(); ~sptr(); /** * @brief Constructor with specified object to be managed. * * @note Null sptr will be created if `other` is a `nullptr`. * @param other Object to be managed by wptr. */ sptr(T *other); /** * @brief Copy Constructor for sptr with different managed class type(T). * * @param other Input sptr object. */ sptr(const sptr &other); /** * @brief Move constructor. * * @note `other` will be set to a null sptr. * @param other Input sptr object. */ sptr(sptr &&other); /** * @brief Move assignment operator. * * @param other Input sptr object. * @note Original strong reference in target sptr object will be removed. */ sptr &operator=(sptr &&other); /** * @brief Copy Constructor for sptr with different managed class type(O). * * @tparam O Another specific class type managed by `other`. * @param other Input sptr object. */ template sptr(const sptr &other); /** * @brief Constructor only used in promote process of wptr. * * @param p WeakRefCounter object which hold the reference to the * managed object. * @param force Only used to identify from other constructor. */ inline sptr(WeakRefCounter *p, bool force); /** * @brief Get the pointer to the managed object. * * @return Pointer of the specific managed class type. */ inline T *GetRefPtr() const { return refs_; } /** * @brief Set the pointer to the managed object. * * @param other Another pointer object to be managed by sptr. * @note Avoid using independently, otherwise it will * cause mismatch of reference count and thus memory problems. */ inline void ForceSetRefPtr(T *other); /** * @brief Remove the reference to the managed object held by current sptr. * * @note It will make this sptr a "null sptr". */ void clear(); /** * @brief Type conversion operator. * * @return Raw pointer to the managed object. * @note Sptr object itself will not be converted, only the member raw * pointer returns. */ inline operator T *() const { return refs_; } /** * @brief Dereference operator. * * It will return the object managed by this sptr. * * @return Return reference of specific object managed by sptr. */ inline T &operator*() const { return *refs_; } /** * @brief Member selection operator. * * It will return the specified member of the object managed by this sptr. */ inline T *operator->() const { return refs_; } /** * @brief Logical-NOT operator. Check if sptr is a "null sptr". * * @return Return true if sptr is a "null sptr". */ inline bool operator!() const { return refs_ == nullptr; } /** * @brief Copy assignment operator with specified object to be managed. * * @note Original reference will be removed, then new reference to the * input object will be established. * @param other Another object to be managed by this sptr. */ sptr &operator=(T *other); /** * @brief Copy assignment operator for sptr with * same managed class type(T). * * @note Original reference will be removed, this sptr will manage the * same object with the input sptr object. * @param other Another sptr object with same managed class type(T). */ sptr &operator=(const sptr &other); /** * @brief Copy assignment operator for wptr with * same managed class type(T). * * @note Original reference will be removed, this sptr will manage the * same object with the input wptr object. * @note This may fail, then this sptr will turn to be a "null sptr". * @param other Another wptr object with same managed class type(T). */ sptr &operator=(const wptr &other); /** * @brief Copy assignment operator for sptr with * different managed class type(O). * * @note Original reference will be removed, this sptr will manage the * same object with the input sptr object. * @note This sptr will interpret the managed object as a type T. * @param other Another sptr object with different managed class type(O). */ template sptr &operator=(const sptr &other); /** * @brief Equal-to operator between sptr and a raw pointer. * * @param other Input raw pointer. * @return Return true if sptr point to the same object with input * raw pointer. */ bool operator==(const T *other) const; /** * @brief Not-equal-to operator between sptr and a raw pointer. * * @param other Input raw pointer. * @return Return true if sptr does not point to the same object with input * raw pointer. */ inline bool operator!=(const T *other) const { return !operator==(other); } /** * @brief Equal-to operator between sptr and a wptr. * * @param other Input wptr. * @return Return true if sptr and wptr are managing same object. */ bool operator==(const wptr &other) const; /** * @brief Not-equal-to operator between sptr and a wptr. * * @param other Input wptr. * @return Return true if sptr and wptr are not managing same object. */ inline bool operator!=(const wptr &other) const { return !operator==(other); } /** * @brief Equal-to operator between sptrs. * * @param other Input sptr. * @return Return true if two sptrs are managing same object. */ bool operator==(const sptr &other) const; /** * @brief Not-equal-to operator between sptrs. * * @param other Input sptr. * @return Return true if two sptrs are not managing same object. */ inline bool operator!=(const sptr &other) const { return !operator==(other); } private: T *refs_ = nullptr; // Raw pointer to the managed specific object }; template inline void sptr::ForceSetRefPtr(T *other) { refs_ = other; } template inline sptr::sptr() { refs_ = nullptr; } template inline sptr::sptr(T *other) { refs_ = other; if (refs_ != nullptr) { refs_->IncStrongRef(this); } } template inline sptr::sptr(const sptr &other) { refs_ = other.GetRefPtr(); if (refs_ != nullptr) { refs_->IncStrongRef(this); } } template sptr::sptr(sptr &&other) { refs_ = other.GetRefPtr(); other.ForceSetRefPtr(nullptr); } template sptr &sptr::operator=(sptr &&other) { if (refs_ != nullptr) { refs_->DecStrongRef(this); } refs_ = other.GetRefPtr(); other.ForceSetRefPtr(nullptr); return *this; } template template sptr::sptr(const sptr &other) : refs_(other.GetRefPtr()) { if (refs_ != nullptr) { refs_->IncStrongRef(this); } } template inline sptr &sptr::operator=(T *other) { if (other != nullptr) { other->IncStrongRef(this); } if (refs_ != nullptr) { refs_->DecStrongRef(this); } refs_ = other; return *this; } template inline sptr &sptr::operator=(const sptr &other) { T *otherRef(other.GetRefPtr()); if (otherRef != nullptr) { otherRef->IncStrongRef(this); } if (refs_ != nullptr) { refs_->DecStrongRef(this); } refs_ = otherRef; return *this; } template inline sptr &sptr::operator=(const wptr &other) { if (refs_ != nullptr) { refs_->DecStrongRef(this); } if ((other != nullptr) && other.AttemptIncStrongRef(this)) { refs_ = other.GetRefPtr(); } else { refs_ = nullptr; } return *this; } template template sptr &sptr::operator=(const sptr &other) { T *otherRef(other.GetRefPtr()); if (otherRef != nullptr) { otherRef->IncStrongRef(this); } if (refs_ != nullptr) { refs_->DecStrongRef(this); } refs_ = otherRef; return *this; } template inline bool sptr::operator==(const T *other) const { return other == refs_; } template inline bool sptr::operator==(const wptr &other) const { return refs_ == other.GetRefPtr(); } template inline bool sptr::operator==(const sptr &other) const { return refs_ == other.GetRefPtr(); } template void sptr::clear() { if (refs_) { refs_->DecStrongRef(this); refs_ = 0; } } template inline sptr::~sptr() { if (refs_ != nullptr) { refs_->DecStrongRef(this); } } template inline sptr::sptr(WeakRefCounter *p, bool /* force */) { if ((p != nullptr) && p->AttemptIncStrongRef(this)) { refs_ = reinterpret_cast(p->GetRefPtr()); } else { refs_ = nullptr; } } /** * @ingroup SmartPointer * @brief Weak reference smart pointer to a RefBase(or its subclass) object. * * Indirectly reference the RefBase object; * Directly reference the WeakRefCounter object. * * @tparam T Specific class type managed by wptr. * This class must inherit from RefBase. */ template class wptr { template friend class wptr; public: wptr(); /** * @brief Constructor with specified object to be managed. * * This method will create WeakRefCounter object for `other` and set its * weak reference count to 1. * * @note WeakRefCounter object will not be created if `other` is a * `nullptr`. * @param other Object to be managed by wptr. */ wptr(T *other); /** * @brief Copy constructor for wptr with same managed class type(T). * * This method will share the WeakRefCounter object of `other` with this * wptr. Weak reference count in this WeakRefCounter object will be set * properly. * * @param other Another wptr with same managed class type(T). */ wptr(const wptr &other); /** * @brief Copy constructor for sptr with same managed class type(T). * * This method will create WeakRefCounter object for the managed object of * `other`, and set its weak reference count properly. * * @param other Another sptr with same managed class type(T). * @tparam T Specific class type managed by `other`. */ wptr(const sptr &other); /** * @brief Copy constructor for wptr with different managed class type(O). * * Same with wptr::wptr(const wptr &other). * * @tparam O Class type managed by `other`. * @param other Another wptr with different managed class type(O). * @tparam T Specific class type managed by `other`. */ template wptr(const wptr &other); /** * @brief Copy constructor for sptr with different managed class type(O). * * Same with wptr::wptr(const sptr &other). * * @param other Another sptr with same managed class type(O). * @tparam T Specific class type managed by `other`. */ template wptr(const sptr &other); /** * @brief Copy assignment operator with specified object to be managed. * * @note Current wptr will unbind the original WeakRefCounter object and * create a new WeakRefCounter object, then set its weak reference count * properly. * @param other Another object to be managed by this wptr. */ wptr &operator=(T *other); /** * @brief Copy assignment operator with specified object to be managed. * * @note Same with wptr &operator=(T *other), but a pointer type casting * which will not affect the type of `*other` is proccessed. * @tparam O Specific class type managed by `other`. * @param other Another object to be managed by this wptr. * */ template wptr &operator=(O *other); /** * @brief Copy assignment operator for wptr with same managed class type(T). * * @note Current wptr will unbind the original WeakRefCounter object and * share the WeakRefCounter object with `other`, then set its weak * reference count properly. * @param other Another wptr. Object managed by it will also be managed by * this wptr. */ wptr &operator=(const wptr &other); /** * @brief Copy assignment operator for sptr with * same managed class type(T). * * @note Current wptr will unbind the original WeakRefCounter object and * create a new WeakRefCounter object, then set its weak reference count * properly. * @param other A sptr object. Object managed by it will also be managed by * this wptr. */ wptr &operator=(const sptr &other); /** * @brief Copy assignment operator for wptr with * different managed class type(O). * * @note Same with wptr &operator=(const wptr &). Note that no cast * here is proccessed. * @param other An wptr object. Object managed by it will also be managed by * this wptr. * @tparam O Specific class type managed by `other`. */ template wptr &operator=(const wptr &other); /** * @brief Copy assignment operator for sptr with * different managed class type(O). * * @note Same with wptr &wptr::operator=(const sptr &). Note that * no cast here is proccessed. * @param other An sptr object. Object managed by it will also be managed by * this wptr. * @tparam O Specific class type managed by `other`. */ template wptr &operator=(const sptr &other); /** * @brief Dereference operator. It will return the object managed by this * wptr. * * @return Return specific object managed by wptr. */ inline T &operator*() const { return *GetRefPtr(); } /** * @brief Member selection operator. * * It will return the specified member of the object managed by this wptr. */ inline T *operator->() const { return reinterpret_cast(refs_->GetRefPtr()); } /** * @brief Equal-to operator between wptr and a raw pointer. * * @param other Input raw pointer. * @return Return true if two pointers have same value. */ bool operator==(const T *other) const; /** * @brief Not-equal-to operator between wptr and a raw pointer. * * @param other Input raw pointer. * @return Return true if two pointers have different value. */ inline bool operator!=(const T *other) const { return !operator==(other); }; /** * @brief Equal-to operator between two wptrs. * * @param other Input reference of a wptr object. * @return Return if two pointers have same value. */ bool operator==(const wptr &other) const; /** * @brief Not-equal-to operator between two wptrs. * * @param other Input reference of a wptr object. * @return Return if two pointers have different value. */ inline bool operator!=(const wptr &other) const { return !operator==(other); } /** * @brief Equal-to operator between wptr and a input sptr object. * * @param other Input reference of an sptr object. * @return Comparison result. */ bool operator==(const sptr &other) const; /** * @brief Not-Equal-to operator between wptr and a input sptr object. * * @param other Input reference of an sptr object. * @return Comparison result. */ inline bool operator!=(const sptr &other) const { return !operator==(other); } /** * @brief Get the pointer to the RefBase object. * * @return Raw pointer to the RefBase object. * @note Return `nullptr` if the managed object has been deallocated. */ T *GetRefPtr() const; /** * @brief Get the count value of corresponding WeakRefCounter object. * * The value indicates how many wptrs share the same WeakRefCounter object. * * @return Value of the count. * @note Only for test. */ inline int GetWeakRefCount() const { return refs_->GetWeakRefCount(); } /** * @brief Attempt to increment the strong reference count of * the managed object. * * @return Return true after a success increment. * @note Avoid using it independently. Use `promote()`. */ inline bool AttemptIncStrongRef(const void *objectId) const { return refs_->AttemptIncStrongRef(objectId); } /** * @brief Promote a wptr to an sptr. * * It will create an sptr object based on * object managed by this wptr. * * @note Original weak reference will be retained. Promote may fail, * and then return a "null sptr". */ const sptr promote() const; ~wptr(); private: WeakRefCounter *refs_ = nullptr; // Pointer to the corresponding weak reference counter object }; template inline T *wptr::GetRefPtr() const { return (refs_ != nullptr) ? reinterpret_cast(refs_->GetRefPtr()) : nullptr; } template wptr::wptr() { refs_ = nullptr; } template wptr::wptr(T *other) { if (other != nullptr) { refs_ = other->CreateWeakRef(other); if (refs_ != nullptr) { refs_->IncWeakRefCount(this); } } else { refs_ = nullptr; } } template wptr::wptr(const wptr &other) { refs_ = other.refs_; if (refs_ != nullptr) { refs_->IncWeakRefCount(this); } } template wptr::wptr(const sptr &other) { if (other.GetRefPtr() != nullptr) { refs_ = other->CreateWeakRef(other.GetRefPtr()); if (refs_ != nullptr) { refs_->IncWeakRefCount(this); } } } template template wptr::wptr(const wptr &other) { refs_ = other.refs_; if (refs_ != nullptr) { refs_->IncWeakRefCount(this); } } template template wptr::wptr(const sptr &other) { if (other.GetRefPtr() != nullptr) { refs_ = other->CreateWeakRef(other.GetRefPtr()); if (refs_ != nullptr) { refs_->IncWeakRefCount(this); } } } template wptr &wptr::operator=(T *other) { WeakRefCounter *newWeakRef = nullptr; if (other != nullptr) { newWeakRef = other->CreateWeakRef(other); if (newWeakRef != nullptr) { newWeakRef->IncWeakRefCount(this); } } if (refs_ != nullptr) { refs_->DecWeakRefCount(this); } refs_ = newWeakRef; return *this; } template template wptr &wptr::operator=(O *other) { T *object = reinterpret_cast(other); WeakRefCounter *newWeakRef = nullptr; if (object != nullptr) { newWeakRef = object->CreateWeakRef(object); if (newWeakRef != nullptr) { newWeakRef->IncWeakRefCount(this); } } if (refs_ != nullptr) { refs_->DecWeakRefCount(this); } refs_ = newWeakRef; return *this; } template inline wptr &wptr::operator=(const wptr &other) { if (other.refs_ != nullptr) { other.refs_->IncWeakRefCount(this); } if (refs_ != nullptr) { refs_->DecWeakRefCount(this); } refs_ = other.refs_; return *this; } template inline wptr &wptr::operator=(const sptr &other) { WeakRefCounter *newWeakRef = nullptr; if (other.GetRefPtr() != nullptr) { newWeakRef = other->CreateWeakRef(other.GetRefPtr()); if (newWeakRef != nullptr) { newWeakRef->IncWeakRefCount(this); } } if (refs_ != nullptr) { refs_->DecWeakRefCount(this); } refs_ = newWeakRef; return *this; } template template wptr &wptr::operator=(const wptr &other) { if (other.refs_ != nullptr) { other.refs_->IncWeakRefCount(this); } if (refs_ != nullptr) { refs_->DecWeakRefCount(this); } refs_ = other.refs_; return *this; } template template wptr &wptr::operator=(const sptr &other) { WeakRefCounter *newWeakRef = nullptr; if (other.GetRefPtr() != nullptr) { newWeakRef = other->CreateWeakRef(other.GetRefPtr()); if (newWeakRef != nullptr) { newWeakRef->IncWeakRefCount(this); } } if (refs_ != nullptr) { refs_->DecWeakRefCount(this); } refs_ = newWeakRef; return *this; } template inline bool wptr::operator==(const T *other) const { return GetRefPtr() == other; } template inline bool wptr::operator==(const wptr &other) const { return GetRefPtr() == other.GetRefPtr(); } template inline bool wptr::operator==(const sptr &other) const { return GetRefPtr() == other.GetRefPtr(); } template inline const sptr wptr::promote() const { return sptr(refs_, true); } template inline wptr::~wptr() { if (refs_ != nullptr) { refs_->DecWeakRefCount(this); } } } // namespace OHOS #endif /**@}*/