/* * Copyright (c) 2021 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 SmartPointer is a pointer-like class. * * This class simulates a pointer while providing * enhanced features, such as automatic memory management.\n * Automatic memory management helps to deallocate * memory resources correctly when an object's life time expires. */ #ifndef UTILS_BASE_REFBASE_H #define UTILS_BASE_REFBASE_H #include #include #ifdef DEBUG_REFBASE #include #endif namespace OHOS { /** * @ingroup SmartPointer * @brief A value indicates no strong references ever. */ #define INITIAL_PRIMARY_VALUE (1 << 28) class RefBase; #if ((defined DEBUG_REFBASE) && (!defined PRINT_TRACK_AT_ONCE)) class RefTracker; #endif /** * @ingroup SmartPointer * @brief Reference counter class. Such a class records two kinds * of references to the corresponding RefBase object and one kind * of references to the RefCounter object itself. * * There are two different references for a single object.\n * A strong reference holds the reference directly pointing to the object, * and the object should be alive as long as the strong reference exists.\n * A weak reference holds a reference indirectly pointing to the object, * and the object is not always alive/existent * even if the weak reference exists. * @note The preceding descriptions are valid only when smart pointers * are properly used. */ class RefCounter { public: /** * @brief Callback function used 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 Sets the callback function. * * @param callback Callback function used to delete * the corresponding RefBase object. */ void SetCallback(const RefPtrCallback& callback); /** * @brief Removes the current callback function by setting it to a `nullptr`. */ void RemoveCallback(); /** * @brief Gets the count of references to the RefCounter object. * * @return Count of references to the RefCounter object. */ int GetRefCount(); /** * @brief Increments the count of references to the RefCounter object by 1. */ void IncRefCount(); /** * @brief Decrements the count of references to the RefCounter object by 1. * * Once the count reaches 0 after being decremented, * `delete this` will be called to deallocate this RefCounter object. */ void DecRefCount(); /** * @brief Checks if the pointer to the callback function is a `nullptr`. * * @return `true` if the callback function is a `nullptr`; * `false` otherwise. */ bool IsRefPtrValid(); /** * @brief Increments the count of strong references to the * corresponding RefBase object by 1. * * @return Original count before increment. */ int IncStrongRefCount(const void *objectId); /** * @brief Decrements the count of strong references to the * corresponding RefBase object by 1. * * @return Original count before decrement. * @note If the strong reference never exists, * decrement will be ineffective. */ int DecStrongRefCount(const void *objectId); /** * @brief Gets the count of strong references to the * corresponding RefBase object. * * @return Count of strong references. */ int GetStrongRefCount(); /** * @brief Increments the count weak references to the * corresponding RefBase object by 1. * * @return Original count before increment. */ int IncWeakRefCount(const void *objectId); /** * @brief Decrements the count of weak references to the * corresponding RefBase object by 1. * * @return Original (before decrement) value of atomicWeak_. * @note If the count reaches 0 after being decremented, the * corresponding RefBase object with no strong reference ever, * or the RefBase object with 0 strong reference but an extended * 'life time', will be deallocated. */ int DecWeakRefCount(const void *objectId); /** * @brief Gets the count of weak references to the * corresponding RefBase object. * * @return Count of weak references. */ int GetWeakRefCount(); /** * @brief Sets the number of attempts to increment. */ void SetAttemptAcquire(); /** * @brief Get the current times of attempts,this interface is only for IPC use. */ int GetAttemptAcquire(); /** * @brief Check if the number of attempts is greater than 0. * * @return `true` if the number of attempts is greater than 0; * `false` otherwise. */ bool IsAttemptAcquireSet(); /** * @brief Clears number of attempts to increment. */ void ClearAttemptAcquire(); /** * @brief Attempts to increment the count of strong references 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 `true` if the attempt is successful; `false` otherwise. */ bool AttemptIncStrongRef(const void *objectId, int &outCount); // Only for IPC use. /** * @brief Attempts to increment the count of strong references to the * the corresponding RefBase object by 1 (simplified). * * @return `true` if the attempt is successful; `false` otherwise. * @note Only for IPC use. */ bool AttemptIncStrong(const void *objectId); /** * @brief Checks if the corresponding RefBase object * has an extended life-time. * * @return `true` if success; `false` otherwise. */ bool IsLifeTimeExtended(); /** * @brief Extends the life-time of corresponding RefBase object. * * This allows the corresponding object keep alive * even if there is no strong reference. * @note The RefBase object will be deallocated * if the count of weak references also reaches 0. */ void ExtendObjectLifetime(); #ifndef EMULATOR_PLATFORM using CanPromote = std::function; void SetCanPromote(const CanPromote& canPromote); void RemoveCanPromote(); bool IsCanPromoteValid(); #endif #if ((defined DEBUG_REFBASE) && (!defined TRACK_ALL)) /** * @brief Enables tracking. It is applicable to debugging only. */ void EnableTracker(); #endif private: void DebugRefBase(const void *objectId); 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_; // Life-time extended flag std::atomic atomicAttempt_; // Number of attempts RefPtrCallback callback_ = nullptr; // 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 EMULATOR_PLATFORM CanPromote canPromote_ = nullptr; #endif #ifdef DEBUG_REFBASE #ifdef TRACK_ALL bool enableTrack = true; #else bool enableTrack = false; #endif std::mutex trackerMutex; // To ensure refTracker be thread-safe #ifdef PRINT_TRACK_AT_ONCE void PrintRefs(const void* objectId); #else RefTracker* refTracker = nullptr; void GetNewTrace(const void* objectId); void PrintTracker(); #endif #endif }; /** * @ingroup SmartPointer * @brief An intermediate class to represent the weak reference * to the correspond RefBase object. * * A WeakRefCounter object can be shared by multiple wptr objects.\n * It holds the references to the corresponding RefBase and RefCounter object. * Those two references will be set as `nullptr` when the weak referenced * target and its RefCounter object are deallocated. The WeakRefCounter * object can remain alive even if the referenced target is deallocated. */ class WeakRefCounter { public: /** * @brief Constructs a WeakRefCounter object. * * @param counter Pointer to corresponding RefCounter object. * @param cookie Pointer to corresponding RefBase object. */ WeakRefCounter(RefCounter *counter, void *cookie); virtual ~WeakRefCounter(); /** * @brief Gets the current pointer to the corresponding RefBase object. * * @return A void pointer to the RefBase object. * If the corresponding object is not alive, a `nullptr` will be returned. * @note A void pointer means that you should cast it to the real type, * since it can be any subclass of RefBase. */ void *GetRefPtr(); /** * @brief Increments the count of references to this WeakRefCounter object. * * @note This count is different from the count of weak references * in RefCounter. It is equal to the count of wptrs directly * referenced to this WeakRefCount object. * @see RefCounter */ void IncWeakRefCount(const void *objectId); /** * @brief Decrements the count of references to this WeakRefCounter object. * * @note This WeakRefCounter object will be deallocated when this count * reaches 0. */ void DecWeakRefCount(const void *objectId); /** * @brief Gets the count recorded by this WeakRefCounter object. * * @return Count recorded by this WeakRefCounter object. * @note The count is different from that in RefCounter. * @see RefCounter::GetWeakRefCount() */ int GetWeakRefCount() const; /** * @brief Attempts to increment the count of strong references to * the corresponding RefBase object (to promote a wptr to a sptr). * * @return `true` after a success increment. */ bool AttemptIncStrongRef(const void *objectId); private: std::atomic atomicWeak_; // Count of references to this // WeakRefCounter object // The value is equal to the count of wptrs // that references this WeakRefCounter object. RefCounter *refCounter_ = nullptr; // Reference to the RefCounter object of // the corresponding RefBase object void *cookie_ = nullptr; // Pointer to the corresponding RefBase object }; /** * @ingroup SmartPointer * @brief A base class of subclasses that can be managed by SmartPointer. * * @note All classes which intend to be managed by SmartPointer should be * derived from RefBase. */ class RefBase { public: RefBase(); /** * @brief Copy constructor of RefBase. * * @note This function constructs a new RefCounter object * and binds it to the RefBase object. */ RefBase(const RefBase &); /** * @brief Copy assignment operator of RefBase. * * @note This function unbinds this RefBase object from the * original RefCounter object, and then binds it to the * 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 function binds this RefBase object with the RefCounter * object of the argument `other`, which will unbind the * RefCounter object. No counts operation will be processed. */ RefBase &operator=(RefBase &&other) noexcept; virtual ~RefBase(); /** * @brief Callback function to deallocate this object. * * This function provides the default implementation to deallocate * this RefBase object by simply calling `delete(this)`. */ virtual void RefPtrCallback(); /** * @brief Extends the life time of the RefBase object. * * @note The object whose life time has been extended will not be * deallocated if the count of weak references, instead of strong * references, reaches 0. */ void ExtendObjectLifetime(); /** * @brief Increments the count of strong references. * * `OnFirstStrongRef()`, which is an empty function by default, * will be called when the first strong reference is established. * * @note This function automatically increments the count of weak * references meanwhile. */ void IncStrongRef(const void *objectId); /** * @brief Decrements the count of strong references. * * If the life time is not extended, this object will be deallocated * when the count of strong references reaches 0.\n * `OnLastStrongRef()`, which is an empty function by default, * will be called when the last strong reference is deleted. */ void DecStrongRef(const void *objectId); /** * @brief Gets the count of strong references. * * @return Count of strong references. The value is 0 if the * corresponding RefCounter object does not exist. * @note This function is valid only when corresponding RefCounter * object exists. */ int GetSptrRefCount(); /** * @brief Creates a weak reference to this RefBase object. * * @param cookie Void pointer to this RefBase object. * @return Pointer to the newly created WeakRefCounter object. * @note Use this function with related functions of wptr. * Do not use it independently. */ WeakRefCounter *CreateWeakRef(void *cookie); /** * @brief Gets the pointer to corresponding counter object. * * @return Pointer to the counter object. */ RefCounter *GetRefCounter() const; /** * @brief Increments the count of weak references. * * @note This function is valid only when corresponding RefCounter * object exists. */ void IncWeakRef(const void *objectId); /** * @brief Decrements the count of weak references. * * @note This function is valid only when corresponding RefCounter * object exists. */ void DecWeakRef(const void *objectId); /** * @brief Gets the count of weak references. * * @return Count of weak references. The value is 0 if the corresponding * RefCounter object does not exist. */ int GetWptrRefCount(); /** * @brief Attempts to increment the count of strong references. * * `OnFirstStrongRef()`, which is an empty function by default, will be * called when the first strong reference is established. * * @return `true` if the increment is successful; `false` otherwise. * @note The count of attempts will increment by 1 * after a successful increment. */ bool AttemptAcquire(const void *objectId); /** * @brief Check attempt acquire is setted,this interface is only for IPC use. * This interface must come after the RefBase::AttemptIncStrong or RefBase::AttemptAcquire function, * And ensuring thread safety in multi-threaded scenarios. * * @note This fuction is extracted from `IncStrongRef()` * It is only for IPC use. */ void CheckIsAttemptAcquireSet(const void *objectId); /** * @brief Attempts to increment the count of strong references. * * `OnFirstStrongRef()`, which is an empty function by default, will be * called when the first strong reference is established. * @return `true` if the increment is successful; `false` otherwise. * @note Use this function in the 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 Attempts to increment the count of strong references. * * @return `true` if the increment is successful; `false` otherwise. * @note If the operation is successful, the count of successful attempts * will increment by 1. * @note This function is a simplified version of `AttemptAcquire`. * It is only for IPC use. */ bool AttemptIncStrong(const void *objectId); /** * @brief Checks if the count of successful attempts is greater than 0. * * @return `true` if the count of successful attempts is greater than 0; * `false` if the count of successful attempts is not greater than 0 * or the corresponding RefCounter object does not exist. */ bool IsAttemptAcquireSet(); /** * @brief Checks if the life time of this RefBase object has been extended. * * @return `true` if the life time of this RefBase object has been extended; * `false` if the RefBase object has a normal life time or the corresponding * RefCounter object does not exist. */ bool IsExtendLifeTimeSet(); /** * @brief Called when the first strong reference is established. * * @note It is an empty function by default. */ virtual void OnFirstStrongRef(const void *); /** * @brief Called when the last strong reference is deleted. * * @note It is an empty function by default. */ virtual void OnLastStrongRef(const void *); /** * @brief Called when the last weak reference is deleted. * * @note It is an empty function by default. */ virtual void OnLastWeakRef(const void *); /** * @brief Called when `wptr::Promote()` is invoked. * * @return `true` if success; `false` otherwise. */ virtual bool OnAttemptPromoted(const void *); /** * @brief Enables tracking of the RefBase object. This function will * be implemented only if DEBUG_REFBASE, but not TRACK_ALL, is defined. */ void EnableTracker(); #ifndef EMULATOR_PLATFORM 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 object * (or an object of its subclass). * * 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 Create a new object with class type (T) and provide a new sptr to manage it. * * @note We strongly recommend using `sptr::MakeSptr` to create a object and manage it. * This approach avoids object pointer leaks, which can avoid many potential memory problems. * * @return A sptr which manage a new object with class type (T). * @param args Constructor parameters of the new object to be managed by sptr. */ template static inline sptr MakeSptr(Args&&... args); /** * @brief Constructor with the specified object to be managed. * And We do not recommend using this interface to create an sptr object. * Using the interface `sptr::MakeSptr` is better * * @note A null sptr will be created if `other` is `nullptr`. * @param other Object to be managed by sptr. */ sptr(T *other); /** * @brief Copy constructor for sptr with the 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 The original strong reference in target sptr object will * be removed. */ sptr &operator=(sptr &&other); /** * @brief Copy Constructor for sptr with the 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 used to promote the process of wptr. * * @param p WeakRefCounter object which hold the reference to the * managed object. * @param force Used to distinguish from other constructors. */ inline sptr(WeakRefCounter *p, bool force); /** * @brief Gets the pointer to the managed object. * * @return Pointer of the specific managed class type. */ inline T *GetRefPtr() const { return refs_; } /** * @brief Sets the pointer to the managed object. * * @param other Another pointer object to be managed by sptr. * @note Avoid using this function independently. Otherwise, * a mismatch of the reference count will arise, leading to memory problems. */ inline void ForceSetRefPtr(T *other); /** * @brief Removes the reference to the managed object held by current sptr. * * @note This function will make this sptr a "null sptr". */ void clear(); /** * @brief Type conversion operator. * * @return Raw pointer to the managed object. * @note The sptr object will not be converted. Only the member raw * pointer will be returned. */ inline operator T *() const { return refs_; } /** * @brief Explicit boolean conversion operator. * * @return `true` if refbase object is not a "null ptr"; `false` otherwise. */ inline explicit operator bool() const { return refs_ != nullptr; } /** * @brief Dereference operator. * * This function will return the object managed by this sptr. * * @return Reference to the specific object managed by sptr. */ inline T &operator*() const { return *refs_; } /** * @brief Member selection operator. * * This function will return the specified member of the object * managed by this sptr. */ inline T *operator->() const { return refs_; } /** * @brief Copy assignment operator with the specified object to be managed. * And We do not recommend using this interface to create an sptr object. * Using the interface `sptr::MakeSptr` is better. * * @note The original reference will be removed, and a 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 * the same managed class type (T). * * @note The original reference will be removed, and the same object * with the input sptr object will be managed by this sptr. * @param other Another sptr object with the same managed class type (T). */ sptr &operator=(const sptr &other); /** * @brief Copy assignment operator for wptr with * the same managed class type (T). * * @note The original reference will be removed, and the same object * with the input wptr object will be managed by this sptr. * @note If the operation fails, this sptr will turn to be a "null sptr". * @param other Another wptr object with the same managed class type (T). */ sptr &operator=(const wptr &other); /** * @brief Copy assignment operator for sptr with * a different managed class type (O). * * @note The original reference will be removed, and the same object * with the input sptr object will be managed by this sptr. * @note This sptr will interpret the managed object as the type (T). * @param other Another sptr object with a different managed class type (O). */ template sptr &operator=(const sptr &other); /** * @brief Equal-to operator between the sptr and raw pointer. * * @param other Input raw pointer. * @return `true` if the sptr points to the same object with input * raw pointer; `false` otherwise. */ bool operator==(const T *other) const; /** * @brief Not-equal-to operator between the sptr and raw pointer. * * @param other Input raw pointer. * @return `true` if the sptr does not point to the same object * with input raw pointer; `false` otherwise. */ inline bool operator!=(const T *other) const { return !operator==(other); } /** * @brief Equal-to operator between the sptr and wptr. * * @param other Input wptr. * @return `true` if the same object is managed by the sptr and wptr; * `false` otherwise. */ bool operator==(const wptr &other) const; /** * @brief Not-equal-to operator between the sptr and wptr. * * @param other Input wptr. * @return `true` if different objects are managed by the sptr and wptr; * `false` otherwise. */ inline bool operator!=(const wptr &other) const { return !operator==(other); } /** * @brief Equal-to operator between two sptrs. * * @param other Input sptr. * @return `true` if the same object is managed by two sptrs; * `false` otherwise. */ bool operator==(const sptr &other) const; /** * @brief Not-equal-to operator between sptrs. * * @param other Input sptr. * @return `true` if different objects are managed by two sptrs; * `false` otherwise. */ inline bool operator!=(const sptr &other) const { return !operator==(other); } private: T *refs_ = nullptr; // Raw pointer to the specific managed object }; template template sptr sptr::MakeSptr(Args&&... args) { T *ptr = new T(std::forward(args)...); sptr res; res.ForceSetRefPtr(ptr); ptr->IncStrongRef(ptr); return res; } 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 object * (or an object of its subclass). * * A weak reference indirectly references the RefBase object * and directly references 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 the specified object to be managed. * * This function will create WeakRefCounter object for `other` * and set the count of weak references to 1. * * @note A 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 the same managed class type (T). * * This function will share the WeakRefCounter object of `other` with this * wptr and set the count of weak references properly. * * @param other Another wptr with the same managed class type (T). */ wptr(const wptr &other); /** * @brief Copy constructor for sptr with the same managed class type (T). * * This function will create a WeakRefCounter object for the managed * object of `other`, and set the count of weak references properly. * * @param other Another sptr with the same managed class type (T). * @tparam T Specific class type managed by `other`. */ wptr(const sptr &other); /** * @brief Copy constructor for wptr with a different managed class type (O). * * This function is the same as wptr::wptr(const wptr &other). * * @tparam O Class type managed by `other`. * @param other Another wptr with a different managed class type (O). * @tparam T Specific class type managed by `other`. */ template wptr(const wptr &other); /** * @brief Copy constructor for sptr with a different managed class type (O). * * This function is the same as wptr::wptr(const sptr &other). * * @param other Another sptr with the same managed class type (O). * @tparam T Specific class type managed by `other`. */ template wptr(const sptr &other); /** * @brief Copy assignment operator with the specified object to be managed. * * @note The current wptr will unbind the original WeakRefCounter object, * create a new WeakRefCounter object, and then set the count of weak * references properly. * @param other Another object to be managed by this wptr. */ wptr &operator=(T *other); /** * @brief Copy assignment operator with the 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 processed. * @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 the same managed class * type (T). * * @note The current wptr will unbind the original WeakRefCounter object, * share the WeakRefCounter object with `other`, and then set the count of * weak references properly. * @param other Another wptr object. Objects managed by it will also be * managed by this wptr. */ wptr &operator=(const wptr &other); /** * @brief Copy assignment operator for sptr with the same managed class * type (T). * * @note The current wptr will unbind the original WeakRefCounter object, * create a new WeakRefCounter object, and then set the count of weak * references properly. * @param other A sptr object. Objects managed by it will also be * managed by this wptr. */ wptr &operator=(const sptr &other); /** * @brief Copy assignment operator for wptr with a different managed class * type (O). * * @note This function is the same as wptr &operator=(const wptr &). * Note that no cast here is processed. * @param other An wptr object. Objects 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 a different managed class * type (O). * * @note This function is the same as * wptr &wptr::operator=(const sptr &). * Note that no cast here is processed. * @param other An sptr object. Objects 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. * * This function will return the object managed by this wptr. * * @return Specific object managed by wptr. */ inline T &operator*() const { return *GetRefPtr(); } /** * @brief Member selection operator. * * This function will return the specified object member managed * by this wptr. */ inline T *operator->() const { return reinterpret_cast(refs_->GetRefPtr()); } /** * @brief Equal-to operator between the wptr and raw pointer. * * @param other Input raw pointer. * @return `true` if two pointers have the same value; `false` otherwise. */ bool operator==(const T *other) const; /** * @brief Not-equal-to operator between the wptr and raw pointer. * * @param other Input raw pointer. * @return `true` if two pointers have different values; `false` otherwise. */ inline bool operator!=(const T *other) const { return !operator==(other); }; /** * @brief Equal-to operator between two wptrs. * * @param other Input reference to a wptr object. * @return `true` if two pointers have the same value; `false` otherwise. */ bool operator==(const wptr &other) const; /** * @brief Not-equal-to operator between two wptrs. * * @param other Input reference to a wptr object. * @return `true` if two pointers have different values; `false` otherwise. */ inline bool operator!=(const wptr &other) const { return !operator==(other); } /** * @brief Equal-to operator between the wptr and input sptr object. * * @param other Input reference to an sptr object. * @return true` if two pointers have the same value; `false` otherwise. */ bool operator==(const sptr &other) const; /** * @brief Not-equal-to operator between the wptr and input sptr object. * * @param other Input reference to an sptr object. * @return `true` if two pointers have different values; `false` otherwise. */ inline bool operator!=(const sptr &other) const { return !operator==(other); } /** * @brief Gets the pointer to the RefBase object. * * @return Raw pointer to the RefBase object. * @note `nullptr` will be returned if the managed object has been * deallocated. */ T *GetRefPtr() const; /** * @brief Gets the count of weak references in a WeakRefCounter object. * * The value indicates how many wptrs share the same WeakRefCounter object. * * @return Count of weak references. * @note Only for test. */ inline int GetWeakRefCount() const { return refs_->GetWeakRefCount(); } /** * @brief Attempts to increment the count of strong references in * the managed object. * * @return `true` if the increment is successful; `false` otherwise. * @note Avoid using this function independently. Use `promote()` instead. */ inline bool AttemptIncStrongRef(const void *objectId) const { return refs_->AttemptIncStrongRef(objectId); } /** * @brief Promotes a wptr to an sptr. * * This function will create an sptr object based on the object * managed by this wptr. * * @note The original weak reference will be retained. * If the promotion fails, a "null sptr" will be returned. */ const sptr promote() const; ~wptr(); private: WeakRefCounter *refs_ = nullptr; // Pointer to the corresponding WeakRefCounter 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 /**@}*/