Android -- sp、wp智能指针的原理简介

anroid智能指针(wp,sp)学习总结 智能指针sp和wp在android c++源码中使用非常频繁,例如IBinder机制,但是它比c++中普通的智能指针要复杂很多,相信不少android学习者如果c++基础不是很扎实的,看起来会比较吃力和枯燥。本人在android 4.2.2源码基础上对sp和wp的关键代码做了详细解析,着重分析原理,相信您看了该文档,一定会有所收获,一定对sp和wp有新的认识。 立即下载

Android -- sp、wp强弱指针的原理简介


我们知道,Android的native层代码基本都是C/C++的天下;基于这种特点,在native层中大量使用指针来操作对象就在所难免了。由于C/C++需要程序员手动操作管理内存,这就使程序出现内存管理问题的概率大大提高。所以,在Android中就提出了一种新的指针概念:强指针(sp)、弱指针(wp)来代替普通的指针;这种指针基于引用计数,来智能地管理对象指针,并不需要程序员做过多的内存管理操作。

在Android中,为了使用sp、wp,我们设计的类都必须是一个类的子类,那就是RefBase,我们看它的类定义:

//sp和wp已经深入融合到了Android系统native代码中,如果我们想使一个类型支持sp和wp操作,就必须
//让这个类继承RefBase类;从某一个角度来说,RefBase类很类似于Java中的Object类,因为它是所有native类的父类
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;

	//RefBase的一个内部类型,它是管理引用计数的一个重要辅助类
    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 weakref_type;
    class weakref_impl;
    
                            RefBase(const RefBase& o);
            RefBase&        operator=(const RefBase& o);

private:
    friend class ReferenceMover;

    static void renameRefs(size_t n, const ReferenceRenamer& renamer);

    static void renameRefId(weakref_type* ref,
            const void* old_id, const void* new_id);

    static void renameRefId(RefBase* ref,
            const void* old_id, const void* new_id);

        weakref_impl* const mRefs;//用于引用计数
};
类中声明的inc、dec前缀的方法,就是用于操控引用计数的方法,某个指针的引用计数的状态就觉得了它自身的生命周期:何时被回收。

sp、wp虽然叫做强弱指针,但它们实际都是一个模板类,分别看它们的声明:

template <typename T>
class wp
{
public:
    typedef typename RefBase::weakref_type weakref_type;
    
    inline wp() : m_ptr(0) { }

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

    ~wp();  
    ...
    // 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; }
    ...
private:
    template<typename Y> friend class sp;
    template<typename Y> friend class wp;

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

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

    ~sp();
   ...
private:
    template<typename Y> friend class sp;
    template<typename Y> friend class wp;
    void set_pointer(T* ptr);
    T* m_ptr;
};

一、sp、wp的创建和析构过程

接着,我们从一个最常见的示例出发,来看看我们创建wp、sp指针时,都做了哪些工作:

class Example : public RefBase {};

int main()
{
    Example* exa = new Example;//1、创建Example指针对象
    sp<Example> sP(exa);//2、创建sP
    wp<Example> wP(exa);//3、创建wP
    return 0;
}
第一步:
定义一个RefBase的子类类型,作为sp、wp的模板类型,并创建它的一个指针对象。Example没有任何成员,使用它使用父类的构造函数:
RefBase::RefBase()
    : mRefs(new weakref_impl(this))
{
}
weakref_impl* const mRefs;//RefBase::weakref_type子类,用于管理引用计数
mRefs是RefBase::weakref_type类型的指针,这里以当前指针对象为参数初始化了该指针:
    weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE)//初始化强引用计数值
        , mWeak(0)//初始化若引用计数值
        , mBase(base)//mBase是RefBase*类型,指向exa
        , mFlags(0)
        , mStrongRefs(NULL)
        , mWeakRefs(NULL)
        , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
        , mRetain(false)
    {
    }
初始化完成后,第一步的工作就结束了,它主要创建了一个引用计数管理对象,并进行了一些初始化工作。

接着看第二步:
sp的构造函数有多个,这里只看最常见的接收指针类型参数的部分:

template<typename T>
sp<T>::sp(T* other)
        : m_ptr(other) {//m_ptr指向模板类型的实例指针
    if (other)
        other->incStrong(this);
}
这里模板类型T就是Example,简单地调用Example的incStrong()方法。由Example的继承关系可知,实际调用的是父类RefBase的同名方法:
void RefBase::incStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;//RefBase::weakref_type子类
    refs->incWeak(id);//通过原子操作,为弱引用计数值+1;第一次引用时,对象的弱引用计数值为1
    
    refs->addStrongRef(id);//调试作用
    const int32_t c = android_atomic_inc(&refs->mStrong);//通过原子操作,为强引用计数值+1,并返回操作之前的旧值;初始值是 1 << 28
    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)  {//( 1 << 28 ),如果不为初始值,说明,该对象已经被强引用了。这时,直接return;
        return;
    }

    android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);//再执行一次原子加法操作,第一次引用时,此时强引用计数值应为1
    refs->mBase->onFirstRef();//然后在调用该模板类型对象的onFirstRef()方法,这里我们要注意:当一个对象第一次被强引用时,会调用该方法;所以,我们可以在
    						  //该函数中做一些初始化操作,此时作用类似于构造函数,Media部分就有这种设计.
}
至此,一个强引用的创建过程就结束了;我们要记住的是:

  1. 一个sp构造完成后,它内部的对该对象的强引用和弱引用计数都为1
  2. 一个sp构造时,会调用一次模板类型的onFirstRef()函数
再看第三步:
wp的创建过程,先看它的构造函数实现:
template<typename T>
wp<T>::wp(T* other)
    : m_ptr(other)//m_ptr是指向模板类型的一个指针成员变量
{
    if (other) m_refs = other->createWeak(this);//m_refs是指向RefBase::weakref_type类型的指针,它管理引用计数
}
跟前面类似,调用:
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
    mRefs->incWeak(id);//mRefs是RefBase::weakref_type子类型

    return mRefs;
}
调用RefBase::weakref_type::incWeak():
void RefBase::weakref_type::incWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);//weakref_impl是RefBase::weakref_type的子类
    impl->addWeakRef(id);//调试作用
    const int32_t c __unused = android_atomic_inc(&impl->mWeak);//将impl的mWeak计数值,通过原子操作+1;对于第一次被引用,此时该对象的弱引用计数为2
    ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}
整个sp、wp的构建过程就结束了,看到这里,我们应该知道:
  • sp中有一个模板类型指针,指向一个实际的模板类型指针变量;而wp中除了有这样一个变量外,还有一个成员变量指向RefBase::weakref_type类型,用于管理引用计数
  • 当一个实际对象经过sp和wp创建后,它的强引用计数值为1,而弱引用计数值为2
构建过程完成后,我们还有必要看下sp、wp的析构过程,看看实际对象的指针什么时候会被释放。对象解析的顺序与声明相反,所以先看wp的析构过程:
template<typename T>
wp<T>::~wp()
{
    if (m_ptr) m_refs->decWeak(this);//m_refs是RefBase::weakref_type类型
}
直接看它的decWeak()函数:
void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id);//调试不管
    const int32_t c = android_atomic_dec(&impl->mWeak);//弱引用计数减1,经过此步骤后,弱引用计数值为1;原值是2
    ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
    if (c != 1) return;//c=2,return掉

	//判断了一些生命周期标志的情况,如果c值是1,则表明弱引用计数值已经是0了,对象没有被弱引用,此时需要考虑声明周期以及对象释放操作
    if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlive the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        if (impl->mStrong == INITIAL_STRONG_VALUE) {//如果我们的强引用计数为默认值,则表示该对象没有强引用,需要删除对象
            // Special case: we never had a strong reference, so we need to
            // destroy the object now.
            delete impl->mBase;
        } else {//否则删除引用计数管理对象
            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
            delete impl;
        }
    } else {
        // less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
        impl->mBase->onLastWeakRef(id);
        if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
            // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
            // is gone, we can destroy the object.
            delete impl->mBase;//删除实际对象
        }
    }
}
此时模板对象的强引用和弱引用计数值皆为1。
再看sp的析构函数:
template<typename T>
sp<T>::~sp() {
    if (m_ptr)
        m_ptr->decStrong(this);
}
调用:
void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id);//调试不管
    const int32_t c = android_atomic_dec(&refs->mStrong);//强引用计数值减1,此时强引用计数为0;c = 1
#if PRINT_REFS
    ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
    ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
    if (c == 1) {
        refs->mBase->onLastStrongRef(id);//函数体为空,无任何操作
        if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {//自身对象有可能会被删除;mFlags默认值为0,未设置时条件成立
            delete this;//删除自身,这里的this就是实际模板对象,会触发Example的析构调用
        }
    }
    refs->decWeak(id);//此时弱引用计数为1,强引用计数值已经为0,再对弱引用计数做一次原子减法
}
void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id);//调试不管
    const int32_t c = android_atomic_dec(&impl->mWeak);//弱引用计数减1,经过此步骤后,弱引用计数值为0;原值c=1
    ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
    if (c != 1) return;//c=1

	//判断了一些生命周期标志的情况,如果我们没有设置mFlags,则满足此项
    if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {//此时强弱引用计数皆为0,再将计数管理对象删除
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlive the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        if (impl->mStrong == INITIAL_STRONG_VALUE) {//此时不满足
            // Special case: we never had a strong reference, so we need to
            // destroy the object now.
            delete impl->mBase;
        } else {//删除引用计数管理对象
            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
            delete impl;
        }
    } else {
        // less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
        impl->mBase->onLastWeakRef(id);
        if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
            // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
            // is gone, we can destroy the object.
            delete impl->mBase;//删除实际对象
        }
    }
}
再看Example对象的析构过程:
RefBase::~RefBase()
{
    if (mRefs->mStrong == INITIAL_STRONG_VALUE) {
        // we never acquired a strong (and/or weak) reference on this object.
        delete mRefs;
    } else {
        // life-time of this object is extended to WEAK or FOREVER, in
        // which case weakref_impl doesn't out-live the object and we
        // can free it now.
        if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
            // It's possible that the weak count is not 0 if the object
            // re-acquired a weak reference in its destructor
            if (mRefs->mWeak == 0) {
                delete mRefs;
            }
        }
    }
    // for debugging purposes, clear this.
    const_cast<weakref_impl*&>(mRefs) = NULL;
}
这样,所有的对象都已经删除掉。由上可知,强引用计数值为0时,会导致实际对象被删除;弱引用计数值为0时,会导致计数管理对象被删除。

PS:最近在看MediaService的代码,在BpBinder的构造函数中发现了这样一个函数调用;
BpBinder::BpBinder(int32_t handle)
    : mHandle(handle)
    , mAlive(1)
    , mObitsSent(0)
    , mObituaries(NULL)
{
    ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);

    extendObjectLifetime(OBJECT_LIFETIME_WEAK);//拓展生命周期
    IPCThreadState::self()->incWeakHandle(handle);
}
BpBinder是RefBase的子类,它在构造函数中调用了extendObjectLifetime()函数来拓展它的生命周期。我们把这个调用加进我们的示例中,并来分析下该调用的实际意义:
class Example : public RefBase {
   extendObjectLifetime(OBJECT_LIFETIME_WEAK);//拓展生命周期
};

int main()
{
    Example* exa = new Example;//1、创建Example指针对象
    sp<Example> sP(exa);//2、创建sP
    wp<Example> wP(exa);//3、创建wP
    return 0;
}
从上面的分析可知,extendObjectLifetime()并不影响sp、wp的创建流程;所以还是需要从示例的析构过程着手。
extendObjectLifetime()的函数实现如下:
void RefBase::extendObjectLifetime(int32_t mode)
{
    android_atomic_or(mode, &mRefs->mFlags);
}
它的参数值有这三种:
    enum {
        OBJECT_LIFETIME_STRONG  = 0x0000,
        OBJECT_LIFETIME_WEAK    = 0x0001,
        OBJECT_LIFETIME_MASK    = 0x0001
    };
它只会设置Example的成员变量mFlags;由之前的介绍可知wp的析构函数会调用到:
void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id);//调试不管
    const int32_t c = android_atomic_dec(&impl->mWeak);//弱引用计数减1,经过此步骤后,弱引用计数值为1;原值c=2
    ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
    if (c != 1) return;//c=2,直接return

    if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlive the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        if (impl->mStrong == INITIAL_STRONG_VALUE) {
            // Special case: we never had a strong reference, so we need to
            // destroy the object now.
            delete impl->mBase;
        } else {
            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
            delete impl;
        }
    } else {
        // less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
        impl->mBase->onLastWeakRef(id);
        if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
            // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
            // is gone, we can destroy the object.
            delete impl->mBase;
        }
    }
}
由于此时c=2,直接return掉;再看sp的析构调用,由之前介绍,会调用到:
void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id);
    const int32_t c = android_atomic_dec(&refs->mStrong);//强引用计数值减1,此时强引用计数为0;c = 1
#if PRINT_REFS
    ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
    ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
    if (c == 1) {
        refs->mBase->onLastStrongRef(id);//函数体为空,无任何操作
        if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {//我们设置了mFlags:OBJECT_LIFETIME_WEAK,不满足if条件;在强引用计数值为0时,我们没有删掉模板类型对象
            delete this;
        }
    }
    refs->decWeak(id);//此时弱引用计数为1,再对弱引用计数做一次原子减法
}
由于我们设置了mFlags的值,代码中的if条件并不满足,此时并不会删除掉原始对象,即模板类型实例。再看decWeak():
void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id);//调试不管
    const int32_t c = android_atomic_dec(&impl->mWeak);//弱引用计数减1,经过此步骤后,弱引用计数值为0;原值c=1
    ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
    if (c != 1) return;//c=1

	//我们设置了mFlags:OBJECT_LIFETIME_WEAK,此时if条件并不满足,走else分支
    if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlive the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        if (impl->mStrong == INITIAL_STRONG_VALUE) {
            // Special case: we never had a strong reference, so we need to
            // destroy the object now.
            delete impl->mBase;
        } else {
            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
            delete impl;
        }
    } else {
        // less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
        impl->mBase->onLastWeakRef(id);
        if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {//设置的mFlags满足此条件,所以会删除掉模板类型对象
            // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
            // is gone, we can destroy the object.
            delete impl->mBase;//删除模板类型对象,即原始对象
        }
    }
}
原始对象的删除会调用它的析构函数:
RefBase::~RefBase()
{
    if (mRefs->mStrong == INITIAL_STRONG_VALUE) {//mStrong此时为0,不满足if条件
        // we never acquired a strong (and/or weak) reference on this object.
        delete mRefs;
    } else {
        // life-time of this object is extended to WEAK or FOREVER, in
        // which case weakref_impl doesn't out-live the object and we
        // can free it now.
        //设置了mFlags后,此条件满足
        if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
            // It's possible that the weak count is not 0 if the object
            // re-acquired a weak reference in its destructor
            if (mRefs->mWeak == 0) {//弱引用计数经历过两次删除后,mWeak为0
                delete mRefs;//删除计数管理对象
            }
        }
    }
    // for debugging purposes, clear this.
    const_cast<weakref_impl*&>(mRefs) = NULL;//调试,置空指针
}
在析构函数中,引用计数管理对象被删除。由此,我们得出:当我们设置mFlags为OBJECT_LIFETIME_WEAK时,只有当强引用计数和弱引用计数值都为0时,模板类型对象和引用计数对象才会被删除;这明显和前面介绍的没有设置mFlags的过程不同。

二、类型提升

特殊地,我们可以将一个wp指针提升为sp指针,wp提供了一个成员函数来完成这种转换:
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;
}
考虑这种使用场景,来看看它的内部处理流程:
class Example : public RefBase {};

int main()
{
    Example* exa = new Example;
    wp<Example> wP(exa);
    sp<Example> sP = wP.promote();//类型提升
    return 0;
}
当我们创建完wP时,此时强引用计数值应为0,弱引用计数值为1。看attemptIncStrong():
bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
    incWeak(id);//原子加法操作,若引用计数加1,此时过后,弱引用计数为2
    
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    int32_t curCount = impl->mStrong;//此时应为初始值0

    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 (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
            break;
        }
        // the strong count has changed on us, we need to re-assert our
        // situation.
        curCount = impl->mStrong;
    }
    
    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
        if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {//走else分支
            // 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 (android_atomic_cmpxchg(curCount, curCount + 1,
                        &impl->mStrong) == 0) {
                    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 = impl->mStrong;
            }

            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)) {//是否允许强引用加1,此场景下是允许的,返回TRUE
                // 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 = android_atomic_inc(&impl->mStrong);//强引用计数加1,开始处弱引用计数已经加1了
        }

        // 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

    // 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 = impl->mStrong;
    while (curCount >= INITIAL_STRONG_VALUE) {
        ALOG_ASSERT(curCount > INITIAL_STRONG_VALUE,
                "attemptIncStrong in %p underflowed to INITIAL_STRONG_VALUE",
                this);
        if (android_atomic_cmpxchg(curCount, curCount-INITIAL_STRONG_VALUE,
                &impl->mStrong) == 0) {
            break;
        }
        // the strong-count changed on us, we need to re-assert the situation,
        // for e.g.: it's possible the fix-up happened in another thread.
        curCount = impl->mStrong;
    }

    return true;
}
代码中给该对象的强弱引用计数值都自加了1,此时就对象的强引用计数值为1,弱引用计数值为2了。
template<typename T>
void sp<T>::set_pointer(T* ptr) {
    m_ptr = ptr;
}
再将实际对象指针保存到sp中。

PS:在Android native代码中,一般的对象指针都已经被sp、wp等代替了,用了它们,我们无需手动去回收指针对象,这样极大地提升了程序的稳定性。而在大多数的native程序中,sp、wp都只是一个代替普通指针的工具,我们能了解它的原理更好,不了解的话,就把它们当中普通指针来看待就行了。
我觉得这些内容中最要注意的一点就是sp第一次构建完成后,会调用实际对象的onFirstRef()函数;在有些场景中,这一点会很容易被忽略,但确实有一些程序会在onFirstRef()方法中做一些初始化操作;如果不记住这点,碰到这种情况,我们看代码时,可能会觉得有一些困惑,而这个困惑恰恰是可以避免的。


JAVA:Spring Boot3 集成 Spring AI 实现 Skill 开发 本文介绍了如何通过Spring Boot和Spring AI实现大模型技能(Skill)开发,让AI具备调用业务系统能力。文章首先解释了Skill的概念,即AI可调用的业务能力,如查询订单、天气等,并展示了执行流程和整体架构。然后详细介绍了实践样例,包括技术版本、Maven依赖配置、AI服务设置、ChatClient创建和Skill技能注册中心的实现。注册中心提供了技能的注册、查询、启用/禁用等功能,支持按类别管理技能,并能够获取所有可用技能列表。通过这种方式,开发者可以轻松为大模型扩展业务功能调用能力。 阅读详情

相关推荐

说说通用报表控件

我们已经开发有2款WINCC报表控件,一种是固定模板,一种是自定义模板。但是它们有个共同特点,就是数据都是来自WINCC的归档数据库。使用WINCC归档数据库的好处是不需要自己写脚本保存数据。但是有些情况下,我们需要自己保存数据,或者第三方系统通过数据表的方式给我们提供数据。那这样的话,我们之前的两款控件就不支持了。正好有个客户有类似需要,于是加了一天班写了个通用报表控件。之所以说是通用,是因为它可以插入任何支持.NET控件的组态软件中,比如WINCC、IFIX等。并且它不依赖于组态软件自己...

HwLib_的博客 3550

Android 智能指针详解 -- sp

源码基于:Android 7.0相关博文:Android 智能指针详解Android 智能指针详解 -- wp Android 智能指针详解 -- spAndroid 智能指针详解 -- RefBase Android中定义了两种智能指针类型,一种是强指针sp(strong pointer),另外一种是弱指针(weak pointer)。其实称之为强引用和弱引用更合适一些。强指针与一般意义的智能指针概念相同,通过引用计数来记录有多少使用者在使用一个对象,如果所有使用者都放弃了对该对象的引用,则该对象将被自

私房菜 1万+

qemu-system-aarch64参数详解与实战配置指南

本文详细解析了qemu-system-aarch64的核心参数,包括-machine、cpu、smp、m、drive和netdev等关键配置。通过嵌入式内核调试、完整系统运行和外设模拟三大实战场景,提供可直接使用的配置示例与性能优化技巧,帮助开发者在x86主机上高效构建和调试ARM64虚拟环境。

weixin_29197051的博客 352

Android强指针sp和弱指针wp区别(六)

1.强指针与弱指针概述 Android中定义了两种智能指针类型,一种是强指针sp(strong pointer),一种是弱指针(weak pointer). 其实成为强引用和弱引用更合适一些。强指针与一般意义的智能指针概念相同,通过引用计数来记录有多少 使用者在使用一个对象,如果所有使用者都放弃了对该对象的引用,则该对象将被自动销毁。 在Android的源代码中,经常会看到形如:sp、...

Android系统攻城狮 2996

从零到一:在Ubuntu 20.04上搭建ROS1与PX4无人机开发环境

本文详细指导如何在Ubuntu 20.04系统上搭建完整的ROS1与PX4无人机开发环境。内容涵盖ROS Noetic安装、PX4固件源码编译、MAVROS通信桥接以及QGroundControl地面站的配置,并通过Gazebo仿真完成全链路联调测试,为无人机算法开发与验证提供稳定可靠的基础平台。

weixin_29292431的博客 167

Modbus TCP 通信(C#)

【代码】Modbus TCP 通信(C#)

weixin_56229359的博客 1150

android中sp的意义_安卓强指针sp的作用和用法

在安卓中,很多地方都用到了android::sp这种东西,sp其实是一个模板类,实现了强指针,在C++中,如果我们new了一个对象,但是如果在该对象已经没用的时候没有delete掉,那么该对象就会一直占用内存,导致内存泄露,比如下面的程序:class A{public:A(){printf("A::A()\n");}void show(){printf("A::show()\n");}~A(){p...

weixin_34007888的博客 2744

C++ 程序稳定运行一段时间后异常中止?vc6 运行库的bug!!!

事件查看器提示:错误应用程序 xxxxxxx.exe,版本 0.0.0.0,错误模块 MSVCRTD.DLL,版本 6.0.9782.0,错误地址 0x00012b40。这是一个通信方面的软件,需要长期运行,在压力测试时,高负荷连续运行一定天数时必定崩溃,而且都是在msvcrtd.dll中崩溃。后来在dump文件中发现调用栈在是MSVCRTD.DLL模块,跟踪代码发现是在void * __cdecl _heap_alloc_dbg(        size_t nSize,        int nBloc

qingflying的专栏 2680

android 的 sp 智能指针用法介绍 sp<> wp<>

ref:

山云的专栏 2867

第3章: MMU Interval Notifier 区间通知器的核心原理⭐

摘要:区间级内存通知机制分析 本文分析了Linux内核中区间级内存通知机制(mmu_interval_notifier)的设计原理与实现。该机制针对传统全局通知(mmu_notifier)存在的性能开销大、无法精确控制等问题,通过引入区间树(Interval Tree)实现精确匹配,仅当内存变化与注册区间重叠时才触发回调。核心优势包括:1)O(log n + k)的高效查找性能;2)支持独立管理各内存区间;3)实现高并发处理不同区间的失效事件。

图形/计算GPU的驱动与虚拟化技术分享园地 2022

(ICLR 2025)【源码讲解+复现】TIMER-XL: Long-Context Transformers for Unified Time Series Forecasting

本文提出了一种统一的多变量时序预测模型Timer-XL,其核心创新包括:1)采用自回归解码器架构,将多变量时序预测统一为next-token预测问题;2)设计TimeAttention机制,通过相对位置编码和因果掩码捕获时序位置和变量间交互;3)支持长上下文预训练以提升零样本迁移能力。模型架构包含嵌入层、时间感知注意力块和预测头,采用MSE损失进行端到端训练。实验表明该方法在多种时序任务上表现优异,特别是在长跨度预测和少样本场景下。代码实现提供了完整的模型定义、数据加载和训练流程,支持自定义配置参数。

1146

Android13 智能指针sp wp refbase

智能指针(Smart Pointer)是一种用于管理动态分配的内存资源的工具,Android 提供了名为 sp 的智能指针类,也被称为强引用指针,用法和c++指针是一样的,但是sp指针可以根据引用计数来动态管理内存资源,普通指针则只能通过delete来释放内存资源Android中LightRefBase实现了基本的智能指针功能。强指针和弱指针是为了解决循环引用中类死锁问题引起的内存泄露。引用对象继承RefBase,则拥有了强引用计数和弱引用计数的属性。

yihanss的博客 1447

① Django手把手从零开发个人博客-前言

手把手教你从零开始玩转手把手教你从零开始玩转Django,全面学习并了解django的运行机制、开发全流程及线上部署。Django,全面学习并了解django的运行机制、开发全流程及线上部署。 专栏介绍 本套教程遵循Django的设计思想,开门见山,快速切入主题,拒绝拖沓,在实战中学习每一个知识点,提高学习的趣味性以及个人成就感,并且能快速将所学运用到实际项目中。 将从零手把手带着你一步步完成博客的每一个功能,通过实现博客文章列表页、文章详情页、作者页面等功能来学习和了解django的视图查询模块相关知.

轻编程的博客 513

[Android] 智能指针sp与wp

智能指针sp与wp 在AOSP中,Google实现了一套特有的智能指针系统,用来方便C++工程中的内存管理。内存释放是C++工程中非常难处理的一部分,为此一些C++工程都会有自己的智能指针系统,C++11的std中也提供了auto_ptr之类的智能指针的概念。 从auto_ptr说起 我们先看下C++ 11中的auto_ptr,这个比AOSP中的较容易理解。 auto_ptr在memory.h中,...

博客已搬家,请访问新博客https://kswapd.cn,提供更好的阅读体验。 2029

乒乓球比赛抽签编排软件

功能强大的编排软件,能胜任各种赛事,单机,联机,网页各种功能,应有尽有,而且完全免费,纯绿色版!

GRASSHOPPER VIPERS 插件

GRASSHOPPER VIPERS 插件

Android智能指针RefBase、sp、wp解析

在Android系统中,Native层的代码基本都是C++写的,C++跟Java不一样,C++没有垃圾回收机制,C++代码中难于管理new出来对象的释放,稍有不慎就造成内存泄漏。针对此问题,Android中提出了一套类似Java垃圾回收机制的智能指针,采用强指针sp(Strong Pointer)和弱指针wp(Weak Pointer)对目标对象进行应用,实现对象的自动回收。下面我们将从C++的基础知识入手,对Android的智能指针展开逐步的分析。

夕月风 944

Python库 | edx_enterprise-3.35.3-py3-none-any.whl

资源分类:Python库所属语言:Python资源全名:edx_enterprise-3.35.3-py3-none-any.whl资源来源:官方安装方法:https://lanzao.blog.youkuaiyun.com/article/details/101784059

Android Q智能指针sp,wp

概述 java提供了垃圾回收机制,不需要程序员自己手动释放对象,c++对于堆上创建的对象需要手动delete,对于庞大的Android系统来说,对象实在容易因为各种原因被忘记释放,造成内存泄露,所以Android提供了一种智能指针来帮助对象释放,sp强指针,wp弱指针。 主要的类 智能指针主要涉及如下几个类: /system/core/libutils/RefBase.cpp /system/co...

qq_34211365的博客 1679

冷水机组 冷却塔和冷却水泵 冷冻泵的选型.xlsx

冷水机组 冷却塔和冷却水泵 冷冻泵的选型

Android智能指针SP WP使用方法介绍

转自:http://developer.51cto.com/art/201001/180894.htm Android手机操作系统既然是开源的操作系统。那么在具体的文件夹中就会存放着各种相关功能的开源代码。我们在使用的时候可以根据这些源代码进行相应的修改就能轻松的完

learnerz的专栏 1万+

Android智能指针sp wp详解

转自:https://www.cnblogs.com/wanqieddy/archive/2012/05/08/2490402.html 研究Android的时候,经常会遇到sp、wp的东西,网上一搜,原来是android封装了c++中对象回收机制。 说明: 1. 如果一个类想使用智能指针,那么必须满足下面两个条件: a. 该类是虚基类RefBase的子类或间接子类 b. 该类必...

Coding··· 1330

android wp指针使用方法,Android智能指针RefBase、sp、wp解析

[TOC]在Android系统中,Native层的代码基本都是C++写的,C++跟Java不一样,C++没有垃圾回收机制,C++代码中难于管理new出来对象的释放,稍有不慎就造成内存泄漏。针对此问题,Android中提出了一套类似Java垃圾回收机制的智能指针,采用强指针sp(Strong Pointer)和弱指针wp(Weak Pointer)对目标对象进行应用,实现对象的自动回收。下面我们将从...

weixin_39993623的博客 563

android智能指针 sp wp归纳总结

参考牛人的源码分析文章http://blog.youkuaiyun.com/luoshengyang/article/details/6786239 和《深入理解Android》 其中要点: 1、智能指针引用计数框架原理:当父对象要引用子对象时,就对子对象使用强引用计数技术,而当子对象要

JINKAI 2313

android系统核心机制 基础(01)智能指针wp & sp

系列文章解读&说明: Android系统核心机制基础 的 分析主要分为以下部分: android系统核心机制 基础(01)智能指针wp & sp android系统核心机制 基础(02)Thread类解析 android系统核心机制 基础(03)Thread 同步机制 android系统核心机制 基础(04)handler message机制 java android系...

wangdsh的博客 1590

Android中的智能指针:sp和wp

原文: Android中的sp和wp指针 链接:http://blog.youkuaiyun.com/DroidPhone/article/details/5799792 经常会在android的framework代码中发现sp和wp这样的指针,平时看的时候都把他当成一个普通的指针封装过掉了,这几天终于忍不住了,想深入了解一下。   相关的代码: frameworks/ba

xww810319的专栏 1977

安卓的智能指针:sp和wp

PS:在Android native代码中,一般的对象指针都已经被sp、wp等代替了,用了它们,我们无需手动去回收指针对象,这样极大地提升了程序的稳定性。而在大多数的native程序中,sp、wp都只是一个代替普通指针的工具,我们能了解它的原理更好,不了解的话,就把它们当中普通指针来看待就行了。定义一个RefBase的子类类型,作为sp、wp的模板类型,并创建它的一个指针对象。这样,所有的对象都已经删除掉。代码中给该对象的强弱引用计数值都自加了1,此时就对象的强引用计数值为1,弱引用计数值为2了。

qq_34888036的博客 1368

Android 智能指针详解 -- wp

上一篇关于sp的博文,通过 source code 来解释了sp的功能,sp被称为强指针,但是强引用更贴切点。那么弱引用wp到底有什么功能?与sp有什么区别?这一篇通过 source code 来解释。

私房菜 1万+
上一篇: Android -- Vold机制简要分析
下一篇: Android -- IPC通信机制之一Binder简介
第一序列丶
博客等级 码龄11年 249粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值