android智能指针

2022-12-13

Android的C++部分代码中有大量的sp/wp存在,意思是strong pointer和weak pointer,看字面意思就是指针相关的东西。C++是通过new和delete进行内存的分配和释放的,但是有时候开发者会忘记使用delete导致内存泄露,所以Android中就创建了sp/wp等,用于避免内存泄露和提高开发效率。
强指针通过引用计数来记录有多少使用者在使用一个对象,如果所有使用者都放弃了对该对象的引用,则该对象将被自动销毁。弱指针仅仅记录该对象的地址,不能通过弱指针来访问该对象,也就是说不能通过弱智真来调用对象的成员函数或访问对象的成员变量。要想访问弱指针所指向的对象,需首先通过wp所提供的promote()方法将弱指针升级为强指针。弱指针所指向的对象是有可能在其它地方被销毁的,如果对象已经被销毁,wp的promote()方法将返回空指针,这样就能避免出现地址访问错的情况。

sp

system\core\libutils\include\utils\StrongPointer.h
system\core\libutils\StrongPointer.cpp

template
class sp {
public:
    inline sp() : m_ptr(nullptr) { }

    template 
    static inline sp make(Args&&... args);

    static inline sp fromExisting(T* other);
#if defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
    sp(std::nullptr_t) : sp() {}
#else
    sp(T* other);  // NOLINT(implicit)
    template  sp(U* other);  // NOLINT(implicit)
                          sp& operator = (T* other);
    template  sp& operator = (U* other);
#endif

    sp(const sp& other);
    sp(sp&& other) noexcept;

    template sp(const sp& other);  // NOLINT(implicit)
    template sp(sp&& other);  // NOLINT(implicit)

    template 
    static inline sp cast(const sp& other);

    ~sp();

    sp& operator  = (const sp& other);
    sp& operator  = (sp&& other) noexcept;

    template sp& operator = (const sp& other);
    template sp& operator = (sp&& other);

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

    void clear();

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

    // Punt these to the wp<> implementation.
    template
    inline bool operator == (const wp& o) const {
        return o == *this;
    }

    template
    inline bool operator != (const wp& o) const {
        return o != *this;
    }

private:
    template friend class sp;
    template friend class wp;
    void set_pointer(T* ptr);
    static inline void check_not_on_stack(const void* ptr);
    T* m_ptr;
};
  • sp是一个模板类
  • sp有7个构造函数
  • 有6个运算符=重载函数
  • m_ptr 是sp实际引用对象的指针变量,所有的操作都是通过这个变量来进行的。

sp构造函数

template
sp::sp(T* other)
        : m_ptr(other) {
    if (other) {
        check_not_on_stack(other);
        other->incStrong(this);
    }
}
template 
template 
sp::sp(U* other) : m_ptr(other) {
    if (other) {
        check_not_on_stack(other);
        (static_cast(other))->incStrong(this);
    }
}
template
sp::sp(const sp& other)
        : m_ptr(other.m_ptr) {
    if (m_ptr)
        m_ptr->incStrong(this);
}
template 
sp::sp(sp&& other) noexcept : m_ptr(other.m_ptr) {
    other.m_ptr = nullptr;
}
template template
sp::sp(const sp& other)
        : m_ptr(other.m_ptr) {
    if (m_ptr)
        m_ptr->incStrong(this);
}
template template
sp::sp(sp&& other)
        : m_ptr(other.m_ptr) {
    other.m_ptr = nullptr;
}
  • 初始化sp中的指针m_ptr
  • m_ptr调用incStrong函数,进行计数加1

重载运算符赋值

template 
sp& sp::operator=(T* other) {
    T* oldPtr(*const_cast(&m_ptr));
    if (other) {
        check_not_on_stack(other);
        other->incStrong(this);
    }
    if (oldPtr) oldPtr->decStrong(this);
    if (oldPtr != *const_cast(&m_ptr)) sp_report_race();
    m_ptr = other;
    return *this;
}
template
sp& sp::operator =(const sp& other) {
    // Force m_ptr to be read twice, to heuristically check for data races.
    T* oldPtr(*const_cast(&m_ptr));
    T* otherPtr(other.m_ptr);
    if (otherPtr) otherPtr->incStrong(this);
    if (oldPtr) oldPtr->decStrong(this);
    if (oldPtr != *const_cast(&m_ptr)) sp_report_race();
    m_ptr = otherPtr;
    return *this;
}
template 
sp& sp::operator=(sp&& other) noexcept {
    T* oldPtr(*const_cast(&m_ptr));
    if (oldPtr) oldPtr->decStrong(this);
    if (oldPtr != *const_cast(&m_ptr)) sp_report_race();
    m_ptr = other.m_ptr;
    other.m_ptr = nullptr;
    return *this;
}
template template
sp& sp::operator =(const sp& other) {
    T* oldPtr(*const_cast(&m_ptr));
    T* otherPtr(other.m_ptr);
    if (otherPtr) otherPtr->incStrong(this);
    if (oldPtr) oldPtr->decStrong(this);
    if (oldPtr != *const_cast(&m_ptr)) sp_report_race();
    m_ptr = otherPtr;
    return *this;
}
template template
sp& sp::operator =(sp&& other) {
    T* oldPtr(*const_cast(&m_ptr));
    if (m_ptr) m_ptr->decStrong(this);
    if (oldPtr != *const_cast(&m_ptr)) sp_report_race();
    m_ptr = other.m_ptr;
    other.m_ptr = nullptr;
    return *this;
}
template template
sp& sp::operator =(U* other) {
    T* oldPtr(*const_cast(&m_ptr));
    if (other) (static_cast(other))->incStrong(this);
    if (oldPtr) oldPtr->decStrong(this);
    if (oldPtr != *const_cast(&m_ptr)) sp_report_race();
    m_ptr = other;
    return *this;
}

make函数

template 
template 
sp sp::make(Args&&... args) {
    T* t = new T(std::forward(args)...);
    sp result;
    result.m_ptr = t;
    t->incStrong(t);  // bypass check_not_on_stack for heap allocation
    return result;
}
  • sp实际就是一个引用,不会单独的申请内存,对引用对象的初始化是在make中
  • 初始化m_ptr指针
  • 引用计数加一

sp析构函数

template
sp::~sp() {
    if (m_ptr)
        m_ptr->decStrong(this);
}
  • 这里调用decStrong函数,把m_ptr的引用次数进行减一

RefBase

在前面的分析中我们看到了函数incStrong和decStrong,实际上这两个函数的实现都是在RefBase类中,然后所有需要用到智能指针的类都需要继承这个类。

class RefBase
{
public:
            void            incStrong(const void* id) const;
            void            incStrongRequireStrong(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                incWeakRequireWeak(const void* id);
        void                decWeak(const void* id);
        // acquires a strong reference if there is already one.
        bool                attemptIncStrong(const void* id);

        bool                attemptIncWeak(const void* id);
        //! DEBUGGING ONLY: Get current weak ref count.
        int32_t             getWeakCount() const;
        void                printRefs() const;
        void                trackMe(bool enable, bool retain);
    };

            weakref_type*   createWeak(const void* id) const;
            weakref_type*   getWeakRefs() const;

    inline  void            printRefs() const { getWeakRefs()->printRefs(); }

    inline  void            trackMe(bool enable, bool retain)
    { 
        getWeakRefs()->trackMe(enable, retain); 
    }

protected:
                            RefBase();
    virtual                 ~RefBase();
    enum {
        OBJECT_LIFETIME_STRONG  = 0x0000,
        OBJECT_LIFETIME_WEAK    = 0x0001,
        OBJECT_LIFETIME_MASK    = 0x0001
    };
    
            void            extendObjectLifetime(int32_t mode);
            
    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;
};

RefBase构造函数

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

weakref_impl

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

    explicit weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE) //强引用计数 1<<28
        , mWeak(0) //弱引用计数
        , mBase(base)
        , mFlags(OBJECT_LIFETIME_STRONG) //0
    {
    }

    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) { }
};
  • weakref_impl继承于RefBase的内部类weakref_type,但是除构造函数之外其他函数的实现都是空
  • weakref_impl的成员变量指针mBasesp::make中new的对象
  • 个人感觉这个类目前没有啥用途,可能主要意图是google用于debug的吧

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();
}
void RefBase::weakref_type::incWeak(const void* id)
{
    weakref_impl* const impl = static_cast(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);
}
  • 成员变量mStrongmWeak加1,因为mStrong初始化时设置成了1<<28,所以第一次调用的时候减去了1<<28。所以最终两个成员变量的值都表示当前被引用的次数
  • onFirstRef子类如果有需要其他的操作,可以重载这个函数进行实现。

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;
        }
    }
    refs->decWeak(id);
}
void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast(this);
    impl->removeWeakRef(id);
    const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release);

    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) {
            ALOGW("RefBase: Object at %p lost last weak reference "
                    "before it had a strong reference", impl->mBase);
        } else {
            delete impl;
        }
    } else {
        impl->mBase->onLastWeakRef(id);
        delete impl->mBase; //非强引用情况下释放
    }
}
  • 成员变量mStrongmWeak减1
  • 如果减1前,强引用是最后一个,mFlags强引用,就把对象释放,调用对应的析构函数
  • mFlags初始化时赋值OBJECT_LIFETIME_STRONG,目前没有其他地方更改这个值
  • 如果是非强引用的情况下,弱引用的次数为0,则释放对象,调用对应的析构函数

wp

template 
class wp
{
public:
    typedef typename RefBase::weakref_type weakref_type;

    inline wp() : m_ptr(nullptr), m_refs(nullptr) { }

    static inline wp fromExisting(T* other);

    // for more information about this flag, see above
#if defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
    wp(std::nullptr_t) : wp() {}
#else
    wp(T* other);  // NOLINT(implicit)
    template 
    wp(U* other);  // NOLINT(implicit)
    wp& operator=(T* other);
    template 
    wp& operator=(U* other);
#endif

    wp(const wp& other);
    explicit wp(const sp& other);
    template wp(const sp& other);  // NOLINT(implicit)
    template wp(const wp& other);  // NOLINT(implicit)

    ~wp();
    
    wp& operator = (const wp& other);
    wp& operator = (const sp& other);

    template wp& operator = (const wp& other);
    template wp& operator = (const sp& other);

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

    sp promote() const;
    void clear();

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

    COMPARE_WEAK(==)
    COMPARE_WEAK(!=)
    COMPARE_WEAK_FUNCTIONAL(>, std::greater)
    COMPARE_WEAK_FUNCTIONAL(<, std::less)
    COMPARE_WEAK_FUNCTIONAL(<=, std::less_equal)
    COMPARE_WEAK_FUNCTIONAL(>=, std::greater_equal)

    template
    inline bool operator == (const wp& o) const {
        return m_refs == o.m_refs;
    }

    template
    inline bool operator == (const sp& o) const {
        if (o == nullptr) {
          return m_ptr == nullptr;
        } else {
          return m_refs == o->getWeakRefs();
        }
    }

    template
    inline bool operator != (const sp& o) const {
        return !(*this == o);
    }

    template
    inline bool operator > (const wp& o) const {
        if (m_ptr == o.m_ptr) {
            return _wp_compare_(m_refs, o.m_refs);
        } else {
            return _wp_compare_(m_ptr, o.m_ptr);
        }
    }

    template
    inline bool operator < (const wp& o) const {
        if (m_ptr == o.m_ptr) {
            return _wp_compare_(m_refs, o.m_refs);
        } else {
            return _wp_compare_(m_ptr, o.m_ptr);
        }
    }
    template inline bool operator != (const wp& o) const { return !operator == (o); }
    template inline bool operator <= (const wp& o) const { return !operator > (o); }
    template inline bool operator >= (const wp& o) const { return !operator < (o); }

private:
    template friend class sp;
    template friend class wp;

    T*              m_ptr;
    weakref_type*   m_refs;
};
  • 大体上跟sp差不多,也有7个构造函数,6个=运算符重载
  • 增加了wp转换为sp的函数promote

promote

template
sp wp::promote() const
{
    sp result;
    if (m_ptr && m_refs->attemptIncStrong(&result)) {
        result.set_pointer(m_ptr);
    }
    return result;
}
template
void sp::set_pointer(T* ptr) {
    m_ptr = ptr;
}
bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
    incWeak(id);

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

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

    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;
            }
        } else {
            if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
                // it didn't so give-up.
                decWeak(id);
                return false;
            }
            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 (curCount == INITIAL_STRONG_VALUE) {
        impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
                std::memory_order_relaxed);
    }

    return true;
}

总结

  • 需要用智能指针的类都需要继承于RefBase
  • 通过sp::make()进行实际对象的初始化,同时强弱引用计数加1
  • 强引用计数为0时,实际对象被释放
  • Flags为强引用时,弱引用计数为0时,weakref_impl被释放,否则实际对象被释放
  • 目前代码中常见的都是强引用

你可能感兴趣的:(android智能指针)