[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中,Android NDK中也包含此文件,我们可以直接使用std命名空间下面的一些方法,遗憾的是NDK把auto_ptr这部分从memory.h中删掉了,NDK开发没有办法使用auto_ptr。

auto_ptr的用法

// 先定义一个类
class Person {
public:
    Person() {
        cout << "Constructor" << endl;
    }

    ~Person() {
        cout << "deconstructor" << endl;
    }

    void printMsg() {
        cout << "printMsg" << endl;
    }
};

// main
int main() {
    auto_ptr<Person> ptr(new Person);
    // auto_ptr重载了->操作符,我们相当于直接对Person指针进行操作
    ptr->printMsg();
    return 0;
}

看下输出结果

Constructor
printMsg
deconstructor

Person的析构函数正常调用了,这是因为Person的指针的生命周期和auto_ptr绑定在一起了,而auto_ptr又是一个分配在栈中的对象,在函数返回是自动销毁,在auto_ptr的析构函数中会自动将Person指针delete。

 ~auto_ptr() throw() {delete __ptr_;}

auto_ptr存在的问题

auto_ptr存在不少的问题,正因为这些原因,Android团队放弃使用auto_ptr作为智能指针的方案。

  • auto_ptr不能引用指针数组,刚才可以看到auto_ptr的析构中只写了delete,并没有使用delete[]进行删除,所以引用指针数组是需要避免的。
// 避免此写法
auto_ptr<int> ptr(new int[10]);
  • 一个auto_ptr只能引用一个指针,不能出现两个auto_ptr引用同一个的对象的情况。如果出现了那么会造成这个指针被delete两次。

  • auto_ptr不能用于函数参数,函数参数中使用auto_ptr作为参数的话 ,首先会调用auto_ptr的拷贝构造函数,原先的auto_ptr会将当前引用释放,但是仍然会存在提前释放的问题。

// 不要将auto_ptr作为参数传递
int main() {
    auto_ptr<Person> ptr(new Person);
    foo4(ptr);
    foo4(ptr);
    return 0;
}

输出结果

Constructor
printMsg
deconstructor
printMsg

可以看出,析构函数在我们对这个对象操作之前进行调用了,这不是我们期望的,出现这个结果的原因是auto_ptr的原理所致,auto_ptr没有引用计数,唯一安全的使用范围就是函数内。

AOSP中的智能指针

概要

AOSP中有两种类型的智能指针,分别是sp和wp,sp表示强指针,强指针会进行引用计数,引用计数是透过该对象自身维持的,当这个对象的引用为0的时候,sp就会释放这个指针。

wp 表示弱指针,弱指针一般出现在两个对象循环引用的场景,如果两个对象A,B互相引用,那么这两个对象的引用计数都不为0,会出现无法释放的情况。所以如果A,B对象需要互相引用,那么A引用B,或者B引用A的时候一定需要一个弱指针,当对象的强指针计数为0时,删除该对象,如果该对象被弱指针引用,那么必须升级为强指针,否则不能进行任何操作。

如果使用sp, wp引用该对象的话, 类必须继承LightRefBase或者RefBase。
下面看下类关系图。

其中还有一个LightRefBase类,可以单独拿出来分析,它的作用跟RefBase类似,但是问题在于如果类继承自LightRefBase的话,是没有办法使用wp的。

简单来说,关键点是RefBase和LightBase的实现,这两个类管理的引用计数,sp,wp只是增加和减少引用计数。
我们看下一个测试

using namespace android;
class Object : public android::RefBase {

public:
    Object() {
        cout << "constructor" << endl;
    }

    virtual ~Object() {
        cout << "deconstructor " << endl;
    }

    void print() {
        cout << " print " << endl;
    }
};

void refbaseTest() {
    auto *ptr = new Object;
    sp<Object> sp(ptr);
    sp->print();
}

调用这个 refbaseTest时,会在堆中生成一个Object对象,然后交由智能指针进行管理,sp对象生成在栈空间,在方法返回时sp会被析构,此时会更改Object的引用计数,Object的引用计数为0时,会delete 自己。

这个是智能指针最基本的使用,但是AOSP中的使用较为复杂,可能出现下面这些情况 。

void refbaseTest() {
    auto *ptr = new Object;
    sp<Object> sp(ptr);
    caller(sp);
}

void caller(android::sp<Object> sp){
    sp->print();
}

sp作为参数传递,此时会调用sp的拷贝构造函数,此时对象引用计数会再+1,caller返回后会再-1,不会对对象释放造成影响。

我们先来看下具体实现吧,更复杂的场景稍后举例说明。

sp

sp的定义如下:

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

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

    ~sp();

    // Assignment

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

    template<typename U> sp& operator = (const sp<U>& other);
    template<typename U> sp& operator = (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; }
    inline explicit operator bool () const { return m_ptr != nullptr; }

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

可以看出sp中几乎重写了所有对象常用的操作符,目的就是将所有的调用都传递给自身包含的指针,即RefBase的子类。

我们重点看下构造函数和析构函数。

//常用的构造函数
template<typename T>
sp<T>::sp(T* other)
        : m_ptr(other) {
    if (other)
        other->incStrong(this);
}
// 拷贝构造函数
template<typename T>
sp<T>::sp(const sp<T>& other)
        : m_ptr(other.m_ptr) {
    if (m_ptr)
        m_ptr->incStrong(this);
}
// 省略其他构造函数。。。

// 析构函数
template<typename T>
sp<T>::~sp() {
    if (m_ptr)
        m_ptr->decStrong(this);
}


构造函数的作用就是将引用计数加一,析构函数的作用是将引用计数减一,是否删除对象由RefBase和LightRefBase决定。

LightRefBase

LightRefBase实现较为简单,我们先看下LightRefBase如何管理引用计数的,稍后再看下复杂的RefBase。

 template<class T>
    class LightRefBase {
    public:
        inline LightRefBase() : mCount(0) {}

        inline void incStrong(__attribute__((unused)) const void *id) const {
            mCount.fetch_add(1, std::memory_order_relaxed);
        }

        inline void decStrong(__attribute__((unused)) const void *id) const {
            if (mCount.fetch_sub(1, std::memory_order_release) == 1) {
                std::atomic_thread_fence(std::memory_order_acquire);
                delete static_cast<const T *>(this);
            }
        }

        //! DEBUGGING ONLY: Get current strong ref count.
        inline int32_t getStrongCount() const {
            return mCount.load(std::memory_order_relaxed);
        }

        typedef LightRefBase<T> basetype;

    protected:
        inline ~LightRefBase() {}

    private:
        friend class ReferenceMover;

        inline static void renameRefs(size_t /*n*/, const ReferenceRenamer & /*renamer*/) {}

        inline static void renameRefId(T * /*ref*/, const void * /*old_id*/ , const void * /*new_id*/) {}

    private:
        mutable std::atomic<int32_t> mCount;
    };

可以看出LightRefBase中有一个原子类型的mCount来进行引用计数,incStrong和decStrong均直接对该类的mCount操作。

  inline void incStrong(__attribute__((unused)) const void *id) const {
            mCount.fetch_add(1, std::memory_order_relaxed);
        }

        inline void decStrong(__attribute__((unused)) const void *id) const {
            if (mCount.fetch_sub(1, std::memory_order_release) == 1) {
                std::atomic_thread_fence(std::memory_order_acquire);
                delete static_cast<const T *>(this);
            }
        }

在decStrong中可以看出,如果mCount的值为0,那么就会将对象自身delete。

LightRefBase是没有办法配合wp进行使用的,LightRefBase类中没有createWeak之类的方法 ,在模板具体化时就会报错,无法编译。

RefBase

重量级的类是RefBase, 智能指针大量的逻辑都是在RefBase类中进行维护的。我们先看下这个类的定义。

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
    };
    
    // Invoked after creation of initial strong pointer/reference.
    virtual void            onFirstRef();
    // Invoked when either the last strong reference goes away, or we need to undo
    // the effect of an unnecessary onIncStrongAttempted.
    virtual void            onLastStrongRef(const void* id);
    // Only called in OBJECT_LIFETIME_WEAK case.  Returns true if OK to promote to
    // strong reference. May have side effects if it returns true.
    // The first flags argument is always FIRST_INC_STRONG.
    // TODO: Remove initial flag argument.
    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
    // Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either
    // kind goes away.  Unused.
    // TODO: Remove.
    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;
};
RefBase::RefBase()
    : mRefs(new weakref_impl(this))
{
}

可以看出,初始化了一个weakref_impl对象,
mRefs是一个weakref_impl对象指针,我们暂时将他们称为影子对象,这个影子对象的负责维护RefBase中的强弱引用个数。

看下RefBase的incStrong实现


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();
}

可以 看出,该方法是将weakref_impl中的mStrong和mWeak分别加一,mWeak加一是通过incWeak方法进行的。
如果是第一次获得对象引用的话,回调onFirstRef方法。

weak_impl中incWeak方法


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);
}

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.
        }
    }
    // Note that even with only strong reference operations, the thread
    // deallocating this may not be the same as the thread deallocating refs.
    // That's OK: all accesses to this happen before its deletion here,
    // and all accesses to refs happen before its deletion in the final decWeak.
    // The destructor can safely access mRefs because either it's deleting
    // mRefs itself, or it's running entirely before the final mWeak decrement.
    //
    // Since we're doing atomic loads of `flags`, the static analyzer assumes
    // they can change between `delete this;` and `refs->decWeak(id);`. This is
    // not the case. The analyzer may become more okay with this patten when
    // https://bugs.llvm.org/show_bug.cgi?id=34365 gets resolved. NOLINTNEXTLINE
    // 减少弱引用计数
    refs->decWeak(id);
}

decStrong的逻辑如下,如果mStrong的个数为0并且该对象的生命周期是由强引用控制,那么就调用delete this将自己删除。
flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG这个表示对象的生命周期根据强引用还是弱引用控制的,默认是强引用。

如果调用delete this将自身删除,那么会调用RefBase的析构函数。

RefBase::~RefBase()
{
    int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
    // Life-time of this object is extended to WEAK, in
    // which case weakref_impl doesn't out-live the object and we
    // can free it now.
    if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
        // It's possible that the weak count is not 0 if the object
        // re-acquired a weak reference in its destructor
        if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
            delete mRefs;
        }
    } else if (mRefs->mStrong.load(std::memory_order_relaxed)
            == INITIAL_STRONG_VALUE) {
        // We never acquired a strong reference on this object.
        //LOG_ALWAYS_FATAL_IF(mRefs->mWeak.load() != 0,
        //        "RefBase: Explicit destruction with non-zero weak "
        //        "reference count");
        // TODO: Always report if we get here. Currently MediaMetadataRetriever
        // C++ objects are inconsistently managed and sometimes get here.
        // There may be other cases, but we believe they should all be fixed.
        delete mRefs;
    }
    // For debugging purposes, clear mRefs.  Ineffective against outstanding wp's.
    const_cast<weakref_impl*&>(mRefs) = NULL;
}

但是析构函数此时并没有调用delete mRefs将weak_impl对象清除,应该是在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 = 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;
    // 如果弱引用为0
    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) {
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlives the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        // 强引用没有初始化
        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 {
        // This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
        // is gone, we can destroy the object.
        impl->mBase->onLastWeakRef(id);
        delete impl->mBase;
    }
}

delete impl 会将weak_impl清除,至此该对象的生命周期就彻底走完了。

wp

下面我们看下弱引用控制的情况,RefBase同时支持强引用计数和弱引用计数,对象的生命周期默认是由强引用进行管理的,可以使用extendObjectLifetime将该对象的生命周期扩展成弱引用,即弱引用为0时,才会调用delete 删除自身。

wp没有办法直接获取到实际对象指针,需要升级为强引用才可以,如果升级(调用promote方法)过程中对象已经被删除,那么promote()方法会返回空的sp,所以,使用wp的时候需要判断下是否为NULL。

void refbaseTest() {
    wp<Object> ptr(new Object);
    sp<Object> s_ptr = ptr.promote();
    if (s_ptr.get()) {
        s_ptr->print();
    }
}

这个时候,使用wp.promote将指针提升为sp,使用sp访问对象。

该调用的输出为

constructor
 print 
deconstructor 

可以看出,此次promote没有返回NULL,指针升级成功。

下面看下promote失败的情况。

void refbaseTest() {
    wp<Object> w_ptr2 = getwptr();
    sp<Object> s_ptr = w_ptr2.promote();
    if (s_ptr.get()) {
        s_ptr->print();
    }
}

wp<Object> getwptr() {
    wp<Object> w_ptr(new Object);
    w_ptr.promote();
    return w_ptr;
}

先看下结果,这次promote会失败,输出结果为:

constructor
deconstructor 

这次调用是在getwptr()中进行了一次promote,该对象的强引用计数+1,但是随着getwptr返回,强引用计数为0,再次promote会失败。
我们看下具体的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;
}

核心逻辑还是在attemptIncStrong里面的,如果attemptIncStrong返回false,那么会返回空的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);
    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;
            }

            while (curCount > 0) {
                if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                        std::memory_order_relaxed)) {
                    break;
                }
            }

            if (curCount <= 0) {
                // promote() failed, some other thread destroyed us in the
                // meantime (i.e.: strong count reached zero).
                decWeak(id);
                return false;
            }
        } else {
            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 (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
    if (curCount == INITIAL_STRONG_VALUE) {
        impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
                std::memory_order_relaxed);
    }

    return true;
}

代码比较长,我们分段来看。

  while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
        if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                std::memory_order_relaxed)) {
            break;
        }
    }

这段逻辑是,如果强引用的计数大于0,那么直接加一,后面会返回true。


if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
        int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            if (curCount <= 0) {
                decWeak(id);
                return false;
            }
            while (curCount > 0) {
                if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                        std::memory_order_relaxed)) {
                    break;
                }
            }
            if (curCount <= 0) {
                decWeak(id);
                return false;
            }
        }

如果这段逻辑的意思是如果是第一次promote,那么引用计数加一返回true。如果不是第一次promote了, 那么强引用计数又等于0,那么返回false,不允许升级为sp。

正好印证了上面两次的结果。

extendObjectLifetime

这个extendObjectLifetime方法用来扩展对象的生命周期,让对象的生命周期是根据强引用还是弱引用进行销毁。默认是强引用。

下面看下示例

class WeakLifeCycleObject : public Object {
public:
    WeakLifeCycleObject() {
        // 更改生命周期
        extendObjectLifetime(OBJECT_LIFETIME_WEAK);
    }
    virtual ~WeakLifeCycleObject() {
    }
};

void refbaseTest() {
    auto *w_ptr = new WeakLifeCycleObject;
    wp<WeakLifeCycleObject> wp2(w_ptr);
}

结果

constructor
de constructor

如果不更改extendObjectLifetime的话,是不会调用析构函数 的,因为这个对象的强引用个数一直是初始值。
核心删除逻辑在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 = 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;
    // 如果弱引用为0
    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) {
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlives the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        // 强引用没有初始化
        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 {
        // This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
        // is gone, we can destroy the object.
        impl->mBase->onLastWeakRef(id);
        delete impl->mBase;
    }
}

最后else这段,会先回调onLastWeakRef,然后使用delete 删除。

总结下AOSP智能指针和auto_ptr的区别

两者的区别很大,sp操作的引用计数是嵌入在被管理对象里面的, auto_ptr操作的引用管理是嵌入在auto_ptr里面的,也就是说,两个auto_ptr不能同时指向同一个被管理对象,但是两个sp可以指向同一个被管理对象。auto_ptr适合在小范围内局部使用,例如函数内部,不适合作为函数参数传来传去,sp可以在全局范围内使用,可以作为函数参数传来传去。两者之间的这些不同在于它们的实现方法不同,最明显的就是sp指向的对象必须要是从RefBase继承下来的,而auto_ptr指向的对象则不需要从某一个指定的类继承下来


参考:
https://blog.csdn.net/Luoshengyang/article/details/6786239
http://www.cnblogs.com/ider/archive/2011/07/22/cpp_cast_operator_part2.html
http://androidxref.com/9.0.0_r3/xref/system/core/libutils/RefBase.cpp

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页