Android智能指针

C++ RAII对象

RAII的全称是Resource Acquisition Is Initialization,即“资源获取就是初始化”。RAII的做法是使用一个对象,在其构造时获取对应的资源,在对象生命期内控制对资源的访问,使之始终保持有效,最后在对象析构的时候,释放构造时获取的资源。把资源放到对象里面,便可依赖C++的构造函数和析构函数机制,确保对资源的持有和释放。

智能指针便是属于RAII的一种,智能指针是一个用于管理资源的对象,其使用引用计数技术。在智能指针对象构造时,增加它所引用对象的的引用计数,在其析构时,减少它所持有对象的引用计数。当引用对象的引用计数为0时,便释放引用对象。
引用计数存放在引用对象中,在智能指针对象构造时,需要将待引用对象传入到智能指针对象的构造函数中,在构造函数会对引用对象的引用计数加1,当智能指针对象析构时,就将其所引用对象的引用计数减1。

Android内置的智能指针包含三种:轻量级指针、强指针、弱指针。

轻量级指针

轻量级指针通过简单的引用计数技术来维护对象的生命周期,下文从代码角度分析下轻量级指针的实现原理。

LightRefBase 类

// code path: /system/core/include/utils/lightRefBase.h
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 类。LightRefBase是一个模板类,其中模板参数T表示对象的实际类型,它必须是继承了 LightRefBase 类的。其成员变量mCount用来描述对象的的引用计数值,提供了两个public接口 incStrongdecStrong 来增加和减少对象的引用计数值。

PS:在成员函数decStrong中,当对象的引用计数值为1时,其减少之后就会变成0,就表示需要需要释放这个对象所占用的内存了。

轻量级指针的实现类 sp

我们有了轻量级指针所指向的对象,那么这个对象由谁来指向?即谁来调用对象的 incStrongdecStrong 函数?接下来需要真正的轻量级指针的实现类,Android提供的轻量级指针的实现类是 sp ,它也是强指针的实现类,这里仅关注它与轻量级指针相关的实现。

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

    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 类也是一个模板类,模板参数T表示所引用对象的实际类型,该类型必须继承自 LightRefBase 类。sp 也是强指针的实现类,这里仅关注其对于轻量级指针的实现:

T* m_prt;	//该成员变量用于指向所引用的对象,该对象必须继承自 LightRefBase

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<T>::operator =(T* other) {
    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    if (other) other->incStrong(this);
    if (oldPtr) oldPtr->decStrong(this);
    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    m_ptr = other;
    return *this;
}

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

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

sp 类和轻量级相关的就是它的构造函数、赋值操作符以及、析构函数。构造函数和析构函数的逻辑非常简单,构造时将所引用对象的引用计数加1,析构时将所引用对象的引用计数减1,都是调用 LightRefBase 的接口。
它的赋值操作符的逻辑就会稍有点复杂,再次先回忆下智能指针的原理:当引用对象有智能指针指向它时,就会给它的引用计数加1;当指向了所引用对象的智能指针不在指向改对象时,它的引用计数就会减1。赋值函数的逻辑同理,由于智能指针指向的新的对象,就会增加新对象的引用计数,而减少旧对象的引用计数。

UML类图

轻量级指针类图

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章