Android高级——智能指针

智能指针

智能指针是一种能够自动维护对象引用计数的技术

  • 引用了一个实际使用的对象,而不是一个指针
  • 智能指针构造时,增加它所引用的对象的引用计数
  • 智能指针析构时,减少它所引用的对象的引用计数

但智能指针无法解决循环引用问题,引入强引用计数和弱引用计数

  • 对象的生命周期只受强引用计数控制
  • 将有关联的对象划分为“父-子”和“子-父”关系
  • 在“父-子”关系中,“父”对象通过强引用计数来引用“子”对象
  • 而在“子-父”关系中,“子”对象通过弱引用计数来引用“父”对象
  • 如A通过强引用计数来引用B,而B通过弱引用计数来引用A,A的生命周期不受B的影响,当A不再使用时可以安全地释放
  • 当B想要使用A时,先要成功地将A的弱引用计数升级为强引用计数,若升级失败,那么就说明A已经被释放,不能再使用

Android系统提供了三种类型的C++智能指针

  • 轻量级指针——引用计数
  • 强指针——强引用计数
  • 弱指针——弱引用技术

轻量级指针

LightRefBase

一个类的对象要支持使用轻量级指针,需继承LightRefBase,其在frameworks/rs/cpp/util/RefBase.h(Android13)

template <class T>
class LightRefBase
{
public:
    inline LightRefBase() : mCount(0) { }
    inline void incStrong(__attribute__((unused)) const void* id) const {
        __sync_fetch_and_add(&mCount, 1);
    }
    inline void decStrong(__attribute__((unused)) const void* id) const {
        if (__sync_fetch_and_sub(&mCount, 1) == 1) {
            delete static_cast<const T*>(this);
        }
    }
    //! DEBUGGING ONLY: Get current strong ref count.
    inline int32_t getStrongCount() const {
        return mCount;
    }

    typedef LightRefBase<T> basetype;

protected:
    inline ~LightRefBase() { }

private:
    friend class ReferenceMover;
    inline static void moveReferences(void*, void const*, size_t,
            const ReferenceConverterBase&) { }

private:
    mutable volatile int32_t mCount;
};
  • 模板类,T表示对象的实际类型,需继承LightRefBase
  • mCount 描述对象的引用计数值
  • incStrong和decStrong 用来增加/减少它所引用对象的引用计数,减少到0释放内存

sp

sp用于轻量级指针,同时也用于强指针,其在frameworks/rs/cpp/util/StrongPointer.h(Android13)

template <typename T>
class sp
{
public:
    inline sp() : m_ptr(0) { }

    sp(T* other);  // NOLINT, implicit
    sp(const sp<T>& other);
    template<typename U> sp(U* other);  // NOLINT, implicit
    template<typename U> sp(const sp<U>& other);  // NOLINT, implicit

    ~sp();

    // Assignment

    sp& operator = (T* other);
    sp& operator = (const sp<T>& other);

    template<typename U> sp& operator = (const sp<U>& other);
    template<typename U> sp& operator = (U* other);

    //! Special optimization for use by ProcessState (and nobody else).
    void force_set(T* other);

    // Reset

    void clear();

    // Accessors

    inline  T&      operator* () const  { return *m_ptr; }
    inline  T*      operator-> () const { return m_ptr;  }
    inline  T*      get() const         { return m_ptr; }

    // Operators

    COMPARE(==)
    COMPARE(!=)
    COMPARE(>)
    COMPARE(<)
    COMPARE(<=)
    COMPARE(>=)

private:
    template<typename Y> friend class sp;
    template<typename Y> friend class wp;
    void set_pointer(T* ptr);
    T* m_ptr;
};
  • 模板类,T表示对象的实际类型,需继承LightRefBase
  • m_ptr 在构造函数中初始化,指向实际引用的对象

sp类的构造函数如下,初始化m_ptr(指向LightRefBase子类),调用LightRefBase类incStrong增加它的引用计数

template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
  {
    if (other) other->incStrong(this);
  }

sp类的析构函数如下,调用 LightRefBase类decStrong 减少它的引用计数

template<typename T>
sp<T>::~sp()
{
    if (m_ptr) m_ptr->decStrong(this);
}

实例分析

external/lightpointer/lightpointer.cpp


强指针和弱指针

RefBase

一个类的对象要支持使用轻量级指针,需继承RefBase,其在frameworks/rs/cpp/util/RefBase.h(Android13)

class RefBase
{
public:
            void            incStrong(const void* id) const;
            void            decStrong(const void* id) const;

            void            forceIncStrong(const void* id) const;

            //! DEBUGGING ONLY: Get current strong ref count.
            int32_t         getStrongCount() const;

    class weakref_type
    {
    public:
        RefBase*            refBase() const;

        void                incWeak(const void* id);
        void                decWeak(const void* id);

        // acquires a strong reference if there is already one.
        bool                attemptIncStrong(const void* id);

        // acquires a weak reference if there is already one.
        // This is not always safe. see ProcessState.cpp and BpBinder.cpp
        // for proper use.
        bool                attemptIncWeak(const void* id);

        //! DEBUGGING ONLY: Get current weak ref count.
        int32_t             getWeakCount() const;

        //! DEBUGGING ONLY: Print references held on object.
        void                printRefs() const;

        //! DEBUGGING ONLY: Enable tracking for this object.
        // enable -- enable/disable tracking
        // retain -- when tracking is enable, if true, then we save a stack trace
        //           for each reference and dereference; when retain == false, we
        //           match up references and dereferences and keep only the
        //           outstanding ones.

        void                trackMe(bool enable, bool retain);
    };

            weakref_type*   createWeak(const void* id) const;

            weakref_type*   getWeakRefs() const;

            //! DEBUGGING ONLY: Print references held on object.
    inline  void            printRefs() const { getWeakRefs()->printRefs(); }

            //! DEBUGGING ONLY: Enable tracking of object.
    inline  void            trackMe(bool enable, bool retain)
    {
        getWeakRefs()->trackMe(enable, retain);
    }

    typedef RefBase basetype;

protected:
                            RefBase();
    virtual                 ~RefBase();

    //! Flags for extendObjectLifetime()
    enum {
        OBJECT_LIFETIME_STRONG  = 0x0000,
        OBJECT_LIFETIME_WEAK    = 0x0001,
        OBJECT_LIFETIME_MASK    = 0x0001
    };

            void            extendObjectLifetime(int32_t mode);

    //! Flags for onIncStrongAttempted()
    enum {
        FIRST_INC_STRONG = 0x0001
    };

    virtual void            onFirstRef();
    virtual void            onLastStrongRef(const void* id);
    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
    virtual void            onLastWeakRef(const void* id);

private:
    friend class ReferenceMover;
    static void moveReferences(void* d, void const* s, size_t n,
            const ReferenceConverterBase& caster);

private:
    friend class weakref_type;
    class weakref_impl;

                            RefBase(const RefBase& o);
            RefBase&        operator=(const RefBase& o);

        weakref_impl* const mRefs;
};                                           
  • 不同于LightRefBase,使用weakref_impl对象(即mRefs)维护对象的引用计数,而非整数

weakref_impl

weakref_impl同时为对象提供了强引用计数和弱引用计数,其在./system/core/libutils/RefBase.cpp(Android13)

class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
    std::atomic<int32_t>    mStrong;
    std::atomic<int32_t>    mWeak;
    RefBase* const          mBase;
    std::atomic<int32_t>    mFlags;

#if !DEBUG_REFS

    explicit weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE)
        , mWeak(0)
        , mBase(base)
        , mFlags(OBJECT_LIFETIME_STRONG)
    {
    }

    void addStrongRef(const void* /*id*/) { }
    void removeStrongRef(const void* /*id*/) { }
    void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
    void addWeakRef(const void* /*id*/) { }
    void removeWeakRef(const void* /*id*/) { }
    void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
    void printRefs() const { }
    void trackMe(bool, bool) { }

#else
	......
#endif
};
  • weakref_impl 继承了 weakref_type,并实现其中方法
  • mStrong / mWeak 描述强/弱引用计数,mBase指向它所引用对象的地址

mFlags 描述对象生命周期控制方法

  • 0:只受强引用计数影响
  • OBJECT_LIFETIME_WEAK:同时受强/弱引用计数影响
  • OBJECT_LIFETIME_FOREVER:完全不受强/弱引用计数影响

强指针

sp

强指针实现类为sp,同上

sp构造函数

T为继承RefBase的子类

template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
  {
    if (other) other->incStrong(this);
  }

实际调用RefBase的incStrong,RefBase在构造函数初始化mRefs

RefBase::RefBase()
    : mRefs(new weakref_impl(this))
{
}

void RefBase::incStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->incWeak(id);

    refs->addStrongRef(id);
    const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
    ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
#if PRINT_REFS
    ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
    if (c != INITIAL_STRONG_VALUE)  {
        return;
    }

    int32_t old __unused = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE, std::memory_order_relaxed);
    // A decStrong() must still happen after us.
    ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old);
    refs->mBase->onFirstRef();
}

void RefBase::weakref_type::incWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->addWeakRef(id);
    const int32_t c __unused = impl->mWeak.fetch_add(1,
            std::memory_order_relaxed);
    ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}
  • 调用 incWeak 将this转为weakref_impl并调用mWeak.fetch_add增加弱引用计数
  • 调用 mStrong.fetch_add 增加强引用计数
  • 若是第一次被强指针引用,调用fetch_sub将强引用计数值设置为1(默认为INITIAL_STRONG_VALUE),然后调用 onFirstRef 处理相关业务,默认为空实现,需要子类自行实现
  • 弱引用计数>=强引用计数

sp析构函数

同理,T为继承RefBase的子类

template<typename T>
sp<T>::~sp()
{
    if (m_ptr) m_ptr->decStrong(this);
}

实际调用RefBase的decStrong

void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id);
    const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);
#if PRINT_REFS
    ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
    LOG_ALWAYS_FATAL_IF(BAD_STRONG(c), "decStrong() called on %p too many times",
            refs);
    if (c == 1) {
        std::atomic_thread_fence(std::memory_order_acquire);
        refs->mBase->onLastStrongRef(id);
        int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            delete this;
            // The destructor does not delete refs in this case.
        }
    }
    refs->decWeak(id);
}

RefBase::~RefBase()
{
    int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
    if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
        if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
            delete mRefs;
        }
    } else if (mRefs->mStrong.load(std::memory_order_relaxed) == INITIAL_STRONG_VALUE) {
        ALOGW("RefBase: Explicit destruction, weak count = %d (in %p). Use sp<> to manage this "
              "object.",
              mRefs->mWeak.load(), this);

#if CALLSTACK_ENABLED
        CallStack::logStack(LOG_TAG);
#endif
    }
    // For debugging purposes, clear mRefs.  Ineffective against outstanding wp's.
    const_cast<weakref_impl*&>(mRefs) = nullptr;
}

void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id);
    const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release);
    LOG_ALWAYS_FATAL_IF(BAD_WEAK(c), "decWeak called on %p too many times",
            this);
    if (c != 1) return;
    atomic_thread_fence(std::memory_order_acquire);

    int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
    if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
        if (impl->mStrong.load(std::memory_order_relaxed)
                == INITIAL_STRONG_VALUE) {
            // Decrementing a weak count to zero when object never had a strong
            // reference.  We assume it acquired a weak reference early, e.g.
            // in the constructor, and will eventually be properly destroyed,
            // usually via incrementing and decrementing the strong count.
            // Thus we no longer do anything here.  We log this case, since it
            // seems to be extremely rare, and should not normally occur. We
            // used to deallocate mBase here, so this may now indicate a leak.
            ALOGW("RefBase: Object at %p lost last weak reference "
                    "before it had a strong reference", impl->mBase);
        } else {
            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
            delete impl;
        }
    } else {
        impl->mBase->onLastWeakRef(id);
        delete impl->mBase;
    }
}
  • 调用 mStrong.fetch_sub 减少强引用计数
  • 当为0时调用 onLastStrongRef 处理相关业务,默认为空实现,需要子类自行实现
  • 判断 mFlags 标志位,检查生命周期是否受弱引用计数控制,若为否则释放内存并调用RefBase的析构函数
  • 在RefBase的析构函数中若发现弱引用计数为0则释放mRefs

当一个对象的强引用计数值为0时

  • 当弱引用计数值大于0,只能释放RefBase,不能释放其内部的weakref_impl(因为还有其他的弱指针通过该weakref_impl对象来引用实际的对象)
  • 当弱引用计数值为0,才可以释放weakref_impl

调用 decWeak 将this转为weakref_impl并调用 mWeak.fetch_sub 减少弱引用计数,若为0

  • 若对象的生命周期只受强引用计数控制,且对象从来没有被强指针引用过,则打印输出记录(impl->mBase好像没释放?)
  • 若对象的生命周期只受强引用计数控制,且被强指针引用过,当若弱引用计数为0时,decStrong释放该对象,decWeak释放其内部的weakref_impl
  • 若对象的生命周期受弱引用计数控制或完全不受强/弱引用计数控制,调用onLastWeakRef处理业务并释放对象

弱指针

wp

wp用于弱指针,其在frameworks/rs/cpp/util/RefBase.h(Android13)

template <typename T>
class wp
{
public:
    typedef typename RefBase::weakref_type weakref_type;

    inline wp() : m_ptr(0) { }

    explicit wp(T* other);
    wp(const wp<T>& other);
    explicit wp(const sp<T>& other);
    template<typename U> explicit wp(U* other);
    template<typename U> explicit wp(const sp<U>& other);
    template<typename U> explicit wp(const wp<U>& other);

    ~wp();

    // Assignment

    wp& operator = (T* other);
    wp& operator = (const wp<T>& other);
    wp& operator = (const sp<T>& other);

    template<typename U> wp& operator = (U* other);
    template<typename U> wp& operator = (const wp<U>& other);
    template<typename U> wp& operator = (const sp<U>& other);

    void set_object_and_refs(T* other, weakref_type* refs);

    // promotion to sp

    sp<T> promote() const;

    // Reset

    void clear();

    // Accessors

    inline  weakref_type* get_refs() const { return m_refs; }

    inline  T* unsafe_get() const { return m_ptr; }

    // Operators

    COMPARE_WEAK(==)
    COMPARE_WEAK(!=)
    COMPARE_WEAK(>)
    COMPARE_WEAK(<)
    COMPARE_WEAK(<=)
    COMPARE_WEAK(>=)

    inline bool operator == (const wp<T>& o) const {
        return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
    }
    template<typename U>
    inline bool operator == (const wp<U>& o) const {
        return m_ptr == o.m_ptr;
    }

    inline bool operator > (const wp<T>& o) const {
        return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
    }
    template<typename U>
    inline bool operator > (const wp<U>& o) const {
        return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
    }

    inline bool operator < (const wp<T>& o) const {
        return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
    }
    template<typename U>
    inline bool operator < (const wp<U>& o) const {
        return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
    }
                         inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
    template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
                         inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
    template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
                         inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
    template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }

private:
    template<typename Y> friend class sp;
    template<typename Y> friend class wp;

    T*              m_ptr;
    weakref_type*   m_refs;
};
  • 模板类,T表示对象的实际类型,需继承RefBase
  • m_ptr 在构造函数中初始化,指向实际引用的对象
  • 使用weakref_type类型的变量m_refs维护对象的弱指针引用
  • 弱指针不可以直接操作它所引用的对象,因为它所引用的对象可能是不受弱引用计数控制的
  • 如果需要操作一个弱指针所引用的对象,需要通过promote升级为强指针

wp构造函数

T为继承RefBase的子类

template<typename T>
wp<T>::wp(T* other)
    : m_ptr(other)
{
    if (other) m_refs = other->createWeak(this);
}

实际调用RefBase的createWeak、incWeak在上面有讲

RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
    mRefs->incWeak(id);
    return mRefs;
}

wp析构函数

实际调用RefBase的decWeak,在上面有讲

template<typename T>
wp<T>::~wp()
{
    if (m_ptr) m_refs->decWeak(this);
}

wp promote函数

wp没有重载*和->操作符,故不能直接操作它引用的对象,需要通过promote将弱引用升级为强引用

template<typename T>
sp<T> wp<T>::promote() const
{
    sp<T> result;
    if (m_ptr && m_refs->attemptIncStrong(&result)) {
        result.set_pointer(m_ptr);
    }
    return result;
}

template<typename T>
void sp<T>::set_pointer(T* ptr) {
    m_ptr = ptr;
}

m_refs是该对象内部的弱引用计数器,通过调用attemptIncStrong试图增加该对象的强引用计数,若成功则转变为sp

bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
    incWeak(id);

    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    int32_t curCount = impl->mStrong.load(std::memory_order_relaxed);

    ALOG_ASSERT(curCount >= 0,
            "attemptIncStrong called on %p after underflow", this);

    while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
        // we're in the easy/common case of promoting a weak-reference
        // from an existing strong reference.
        if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                std::memory_order_relaxed)) {
            break;
        }
        // the strong count has changed on us, we need to re-assert our
        // situation. curCount was updated by compare_exchange_weak.
    }

    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
        // we're now in the harder case of either:
        // - there never was a strong reference on us
        // - or, all strong references have been released
        int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            // this object has a "normal" life-time, i.e.: it gets destroyed
            // when the last strong reference goes away
            if (curCount <= 0) {
                // the last strong-reference got released, the object cannot
                // be revived.
                decWeak(id);
                return false;
            }

            // here, curCount == INITIAL_STRONG_VALUE, which means
            // there never was a strong-reference, so we can try to
            // promote this object; we need to do that atomically.
            while (curCount > 0) {
                if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                        std::memory_order_relaxed)) {
                    break;
                }
                // the strong count has changed on us, we need to re-assert our
                // situation (e.g.: another thread has inc/decStrong'ed us)
                // curCount has been updated.
            }

            if (curCount <= 0) {
                // promote() failed, some other thread destroyed us in the
                // meantime (i.e.: strong count reached zero).
                decWeak(id);
                return false;
            }
        } else {
            // this object has an "extended" life-time, i.e.: it can be
            // revived from a weak-reference only.
            // Ask the object's implementation if it agrees to be revived
            if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
                // it didn't so give-up.
                decWeak(id);
                return false;
            }
            // grab a strong-reference, which is always safe due to the
            // extended life-time.
            curCount = impl->mStrong.fetch_add(1, std::memory_order_relaxed);
            // If the strong reference count has already been incremented by
            // someone else, the implementor of onIncStrongAttempted() is holding
            // an unneeded reference.  So call onLastStrongRef() here to remove it.
            // (No, this is not pretty.)  Note that we MUST NOT do this if we
            // are in fact acquiring the first reference.
            if (curCount != 0 && curCount != INITIAL_STRONG_VALUE) {
                impl->mBase->onLastStrongRef(id);
            }
        }
    }

    impl->addStrongRef(id);
                                                                                                                                            654,17        79%
            break;
        }
        // the strong count has changed on us, we need to re-assert our
        // situation. curCount was updated by compare_exchange_weak.
    }

    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
        // we're now in the harder case of either:
        // - there never was a strong reference on us
        // - or, all strong references have been released
        int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            // this object has a "normal" life-time, i.e.: it gets destroyed
            // when the last strong reference goes away
            if (curCount <= 0) {
                // the last strong-reference got released, the object cannot
                // be revived.
                decWeak(id);
                return false;
            }

            // here, curCount == INITIAL_STRONG_VALUE, which means
            // there never was a strong-reference, so we can try to
            // promote this object; we need to do that atomically.
            while (curCount > 0) {
                if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                        std::memory_order_relaxed)) {
                    break;
                }
                // the strong count has changed on us, we need to re-assert our
                // situation (e.g.: another thread has inc/decStrong'ed us)
                // curCount has been updated.
            }

            if (curCount <= 0) {
                // promote() failed, some other thread destroyed us in the
                // meantime (i.e.: strong count reached zero).
                decWeak(id);
                return false;
            }
        } else {
            // this object has an "extended" life-time, i.e.: it can be
            // revived from a weak-reference only.
            // Ask the object's implementation if it agrees to be revived
            if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
                // it didn't so give-up.
                decWeak(id);
                return false;
            }
            // grab a strong-reference, which is always safe due to the
            // extended life-time.
            curCount = impl->mStrong.fetch_add(1, std::memory_order_relaxed);
            // If the strong reference count has already been incremented by
            // someone else, the implementor of onIncStrongAttempted() is holding
            // an unneeded reference.  So call onLastStrongRef() here to remove it.
            // (No, this is not pretty.)  Note that we MUST NOT do this if we
            // are in fact acquiring the first reference.
            if (curCount != 0 && curCount != INITIAL_STRONG_VALUE) {
                impl->mBase->onLastStrongRef(id);
            }
        }
    }

    impl->addStrongRef(id);

#if PRINT_REFS
    ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
#endif

    // curCount is the value of mStrong before we incremented it.
    // Now we need to fix-up the count if it was INITIAL_STRONG_VALUE.
    // This must be done safely, i.e.: handle the case where several threads
    // were here in attemptIncStrong().
    // curCount > INITIAL_STRONG_VALUE is OK, and can happen if we're doing
    // this in the middle of another incStrong.  The subtraction is handled
    // by the thread that started with INITIAL_STRONG_VALUE.
    if (curCount == INITIAL_STRONG_VALUE) {
        impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
                std::memory_order_relaxed);
    }

    return true;
}
  • incWeak 先增加弱引用计数,然后后面判断是否可以增加强引用
  • 将this转为weakref_impl

当强引用计数值大于0,且不等于INITIAL_STRONG_VALUEE,调用compare_exchange_weak增加强引用计数

当强引用计数值小于等于0,或等于INITIAL_STRONG_VALUEE

  • 当生命周期受强引用影响,若强引用小于等于0则无法升级,减少弱引用。否则增加强引用,若增加失败,则减少弱引用
  • 当生命周期受弱引用或完全不受强弱引用影响,调用onIncStrongAttempted判断对象是否允许强引用它,若允许则增加强引用,若在增加前被别人增加了,则调用onLastStrongRef

如果是第一次增加强引用,需要调用mStrong.fetch_sub修正为1

实例分析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/770906.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ctfshow-web入门-文件包含(web78、web79、web80、web81)

目录 1、web78 2、web79 3、web80 4、web81 1、web78 存在文件包含函数&#xff1a;include 直接上 php 伪协议&#xff0c;用 php://filter 读文件&#xff08;flag.php&#xff09;的源码&#xff0c;payload&#xff1a; ?filephp://filter/readconvert.base64-encode…

轻松实现百度大模型ERNIE对话

该代码直接可用&#xff0c;实现了流式输出&#xff0c;只需要在你自己的开发环境配置百度申请的QIANFAN_AK和QIANFAN_SK即可使用啦。// # 在.env文件中&#xff0c;设置以下内容&#xff0c;安全认证Access Key替换your_iam_ak&#xff0c;Secret Key替换your_iam_sk 不过需要…

Linux Ubuntu 将指定ip添加到DNS

请严格按照如下步骤操作 以ip地址&#xff1a;202.96.134.133 为例 1.修改 /etc/resolv.conf 文件 sudo gedit /etc/resolv.conf 添加 nameserver 8.8.8.8 和 nameserver 202.96.134.133&#xff0c; 如下图方框指定内容&#xff1a; 2.修改 /etc/resolvconf/resolv.conf.d…

Python28-7.1降维算法之LDA线性判别分析

线性判别分析&#xff08;Linear Discriminant Analysis, LDA&#xff09;是一种用于模式识别和机器学习的分类和降维技术。LDA通过找到能最大化类别间方差和最小化类别内方差的投影方向&#xff0c;实现样本的降维和分类。 LDA的基本思想 LDA的核心思想是通过线性变换将数据…

Docker学习笔记(一)概念理解

一、什么是docker容器 Docker容器是一种轻量级、可移植的软件封装技术&#xff0c;它允许开发者将应用程序及其依赖、配置文件、运行环境等打包到一个独立的、自包含的执行单元中。容器与虚拟机相似&#xff0c;都提供了隔离的运行环境&#xff0c;但容器更加轻量级&#xff0c…

Echarts折线+柱状图的多y轴

实现效果&#xff1a; 代码&#xff1a; <template><div class"test-echart"><div id"barLineChart" ref"barLineChart" :style"barLineStyle"></div></div> </template> <script> // imp…

MySQL之MHA高可用集群及故障切换

一、MHA概述 MHA&#xff08;MasterHigh Availability&#xff09;是一套优秀的mysql高可用环境下故障切换和主从复制的软件。MHA的出现就是为了解决mysql单点故障。Mysql故障切换过程中&#xff0c;MHA能做到0-30秒内自动完成故障性切换操作。MHA能在故障切换的过程中最大程度…

【路由交换技术】Cisco Packet Tracer基础入门教程(五)

这一期我们来学习端口聚合&#xff0c;这是针对交换机的技术 前言 不知道大家有没有注意到&#xff0c;我们之前的实验在交换机与交换机之间只用一条线连接&#xff0c;像这样 通过今天的学习&#xff0c;我们要用两条线来连接交换机&#xff0c;就像这样&#xff08;为了能…

3D问界—法线空间与应用举例

问题提出&#xff1a;什么是法线空间&#xff0c;有哪些应用的场景&#xff1f; 法线空间&#xff08;Normal Space&#xff09;在计算机图形学中是一个重要的概念&#xff0c;特别是在处理表面法线&#xff08;Normal&#xff09;时常被提及。 1. 法线空间的分类 法线空间是相…

“工控机”是什么?和普通电脑有区别嘛!

在现代工业生产中,有一种特殊的计算机,它不像普通电脑那样被放置于明亮的办公室内,而是常常藏身于机器轰鸣、环境恶劣的工厂车间里,这就是工控机——工业控制计算机的简称。作为工业自动化领域不可或缺的核心设备,工控机不仅承载着监控与数据采集(SCADA)、过程控制、数据…

python 实现docx指定语言翻译(不丢失格式)

我这边有个需求需要把一份docx翻译成指定语言的文档并且保存&#xff0c;研究了下&#xff0c;记录。 首先先安装依赖 pip install python-docx1.1.2 googletrans4.0.0rc1 python-docx是用来读取docx的&#xff0c;googletrans使用来翻译的。 googletrans PyPI 这个是官方文…

【大语言模型系列之Transformer】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

什么是YUV和IPB,PTS和DTS,视频编码解码过程

YUV 是一种在视频处理和压缩中常用的颜色空间。 它将图像的亮度 (Y) 与色度 (U 和 V) 成分分开。 这种分离对视频压缩和广播非常有益&#xff0c; 因为人眼对亮度变化比对颜色变化更敏感。 YUV 组件简介 Y (亮度)&#xff1a;表示图像的亮度或灰度信息。U (色度)&#xff1a;…

每日一练:攻防世界:Hidden-Message

追踪UDP数据流&#xff0c;没有任何隐藏信息&#xff1a; WP&#xff1a; 观察流量包 每个流的唯一的区别就是UDP的源地址srcport的最后一位在变化 都提取出来就是二进制序列 用tshark提取一下 //使用tshark过滤出源端口&#xff0c;使用cut裁取端口的最后一位 tshark -r 8…

[C/C++] -- gdb调试与coredump

1.gdb调试 GDB&#xff08;GNU 调试器&#xff09;是一个强大的工具&#xff0c;用于调试程序。 安装 1. wget http://ftp.gnu.org/gnu/gdb/gdb-8.1.tar.gz 2. tar -zxvf gdb-8.1.1.tar.gz 3. cd gdb-8.1.1 4. ./configure 5. make 6. make install 基础用法 …

git上传文件

git init git add . git commit -m " " git remote add origin 仓库的地址 git push -u origin master 如果出现以下问题 可以用这一句强制上传 git push -f origin master

BME688 环境传感器

型号简介 BME688是博世&#xff08;bosch-sensortec&#xff09;的一款首款具有人工智能 (AI) 和集成高线性度和高精度压力、湿度和温度传感器的气体传感器。它采用坚固而紧凑的 3.0 x 3.0 x 0.9 mm 封装&#xff0c;专为移动和联网应用而开发&#xff0c;在这些应用中&#xf…

C++之boost智能指针

1、boost智能指针 资源获取即初始化&#xff1a;在构造函数中对资源进行初始化&#xff0c;在析构函数中释放。 智能指针的本质思想是&#xff1a;将堆对象的生存期&#xff0c;用栈对象来管理。这个栈对象就是智能指针。 当new 一个堆对象的时候&#xff0c;立刻用智能指针…

共享拼购:创新商业模式引领小用户基数下的销售奇迹“

在瞬息万变的商业蓝海中&#xff0c;一个新颖且深具潜力的策略正悄然改变着游戏规则&#xff0c;它巧妙地避开了传统路径的束缚&#xff0c;以微妙却深远的调整&#xff0c;开辟出了一条通往成功的独特航道。我的一位合作伙伴&#xff0c;正是这一策略的实践者&#xff0c;他在…

Blender渲染慢?那是你还不知道这5个技巧

Blender是一款功能强大且用途广泛的软件&#xff0c;可帮助 3D 艺术家和动画师创作出色的视觉内容。如果您使用过 Blender&#xff0c;您就会知道渲染可能非常耗时。渲染时间过长可能会令人烦恼并限制创造力。 在这篇文章中&#xff0c;我们将提供一些专家提示和想法以加快 Bl…