To understand the implementation of strong pointer in Android system

  • 2021-12-21 04:57:28
  • OfStack

Strong Pointer and Weak Pointer Basis

Smart pointers in android include: lightweight pointers, strong pointers, and weak pointers.
Strong pointer: It mainly maintains the life cycle of objects through strong reference counting.
Weak pointer: It mainly maintains the life cycle of the pointed object through weak reference counting.
If a strong pointer or weak pointer technique is used in a class, then the class must inherit from the class RefBase, because the strong pointer and weak pointer provide the implementation reference counter through the class RefBase.
Strong pointers and weak pointers are more intimate than lightweight pointers, so they are generally used together.

Analysis of Strong Pointer Principle

The following analysis of source code comes from android 5.0 system source code
The implementation of the strong pointer definition is mainly in the\ frameworks\ rs\ cpp\ util\ RefBase. h file


class RefBase
{
public:
            // A member variable is defined to maintain the reference count of strongly referenced objects 
            void            incStrong(const void* id) const;
            // A member variable is defined to maintain the reference count of strongly referenced objects 
            void            decStrong(const void* id) const;
          
            void            forceIncStrong(const void* id) const;

            // Gets the number of strong pointer counts .
            int32_t         getStrongCount() const;
    // This class mainly implements the 
    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;
    // Get counter data through class objects. 
    class weakref_impl;

                            RefBase(const RefBase& o);
            RefBase&        operator=(const RefBase& o);

        weakref_impl* const mRefs;
};

From the above class definition, we can see that weakref_type class is nested in RefBase class, and this weakref_type class is also an object mRefs to describe the reference count of objects. That is, every RefBase object contains one weakref_type object.
virtual is a virtual function, friend is a friend function,

Summarize

If the lifecycle control flag value of an object is set to 0, the system will automatically release the object as long as its strong reference count value is also 0.


Related articles: