• 主页
  • 随笔
所有文章 友链 关于我

  • 主页
  • 随笔

android中的轻量级指针

2021-10-08

智能指针来源

由于android系统底层的很大的一部分是用C++实现的,C++的开发就难免会使用到指针的这个知识 点。而C++的难点和容易出问题的也在于指针。使用指针出错,常常会引发带来对项目具有毁灭性的错误,内存泄漏、逻辑错误、系统崩溃。

引发指针错误情况表现常常有如下几个表现情况:

1.申请了内存空间,但是忘记释放指针所指向的对象占用的内存空间。

2.使用了无效的指针。

因此在android的C++代码部分采用了智能指针的技术。智能指针通过一种能够自动危害对象引用计数的技术。来解决C++中指针存在的缺陷问题。

在android系统中提供了三种类型的C++智能指针,分别为:轻量级智能指针、强指针、弱指针。
下面主要通过进行分析轻量级指针的实现原理。

轻量级指针

轻量级指针就是通过利用简单的引用计数计数类维护对象的生命周期,如果一个类的对象支持使用轻量级指针,那么它就必须要从LightRefBase类进行继承,因为这个LightRefBase类提供了一个简单的引用计数器。

LightRefBase类定义

下面的源码主要依据android5.0的源码进行分析的。LightRefBase类的定义在android系统中的\frameworks\rs\cpp\util\RefBase.h 这个文件中。

LightRefBase类也是一个模板类。模板参数T表示对象的实际类型,它必须进行对LightRefBase这个类继承。

//模板类
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;
};

上面LightRefBase类定义涉及到几个知识点:

1、C++的三个访问权限类型:public、protected、private。

public:可以被任意实体访问。 protected:只允许子类及本类的成员函数访问。 private:只允许本类的成员函数访问。

2、C++中的inline内联函数 在函数第一部分如果包含有inline关键字的函数,那么这个函数就表示为内联函数。内联函数主要为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题。

inline的使用是有所限制的,inline只适合涵数体内代码简单的涵数使用,不能包含复杂的结构控制语句例如while、switch,并且不能内联函数本身不能是直接递归函数(递归函数:自己内部还调用自己的函数)。

3、C++中的friend友元函数

C++中的友元机制允许类的非公有成员被一个类或者函数访问,友元按类型分为三种:普通非类成员函数作为友元,类的成员函数作为友元,类作为友元。

友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend。

4、C++中的mutable关键字
mutable是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。

5、C++中的template类模板
一个类模板(也称为类属类或类生成类)同意用户为类定义一种模式。使得类中的某些数据成员、默写成员函数的參数、某些成员函数的返回值,能够取随意类型(包含系统提前定义的和用户自己定义的)。
类模板的应用场景:多个类有着共同操作,但是数据类型不同。

LightRefBase的实现类

轻量级LightRefBase类的实现类为wp类,它也是在\frameworks\rs\cpp\util\RefBase.h 这个文件中。wp也是一个模板类,模板参数T表示的是对象的实际类型,它必须继承LightRefBase类。由于wp类也是强指针的实现类,因此我们只需要分析下该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();

    // 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;
    //轻量级指针会用到的变量m_ptr
    T*              m_ptr;
    weakref_type*   m_refs;
};

##总结

通过前面的概念和系统源码实现功能原理分析,我们如果要使用轻量级指针的话,那么要包含头文件并采用继承LightRefBase类的方式,那么就可以使用轻量级指针的功能了。

  • Android

展开全文 >>

探索android的强指针实现

2021-10-08

强指针和弱指针基础

android中的智能指针包括:轻量级指针、强指针、弱指针。

强指针:它主要是通过强引用计数来进行维护对象的生命周期。

弱指针:它主要是通过弱引用计数来进行维护所指向对象的生命周期。

如果在一个类中使用了强指针或者弱指针的技术,那么这个类就必须从RefBase这个类进行做继承,因为强指针和弱指针是通过RefBase这个类来提供实现的引用计数器。

强指针和弱指针关系相对于轻量级指针来说更加亲密,因此他们一般是相互配合使用的。

强指针原理分析

以下针对源码的分析都是来源于android5.0系统源码 强指针的定义实现主要在\frameworks\rs\cpp\util\RefBase.h文件中

class RefBase
{
public:
            //定义了成员变量用于维护强引用对象的引用计数
            void            incStrong(const void* id) const;
            //定义了成员变量用于维护强引用对象的引用计数
            void            decStrong(const void* id) const;
          
            void            forceIncStrong(const void* id) const;

            //获取强指针计数的数量.
            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;
};

通过以上类定义可以看到 RefBase类里面嵌套着weakref_type类,这个weakref_type类也的对象mRefs来描述对象的引用计数。也就是说每一个RefBase对象都包含一个weakref_type对象。

virtual表示的是虚函数。

总结

如果一个对象的生命周期控制标志值被设置为0的情况下,只要它的强引用计数值也为0,那么系统就会自动释放这个对象。

  • Android

展开全文 >>

使用 runtime, 让 UserDefaults 飞

2021-07-07

封装 UserDefaults,用属性的方式存取数据

  • 告别字符串硬编码,

  • 统一形式,不再有各种类型存取方法