智能指针是一种抽象的数据类型,它通常是经过类模板完成的,能够完成泛型,并且能够经过类的析构函数自动开释指针所指向的内存或目标。

Android中,有相似 shared_ptrweak_ptr 的智能指针 LightRefBase + spRefBase + wp

其间:

LightRefBase + sp 相似于 shared_ptr 的实践运用办法;

RefBase + wp + sp 相似于 shared_ptr + weak_ptr 的实践运用办法。

weak_ptr 是合作 shared_ptr 运用的,具体能够查看C++四种智能指针

实践原理便是:

经过引证计数来保护目标的生命周期。每逢一个新的指针指向了一个目标时,这个目标的引证计数就添加1,相反每逢一个指针不再指向一个目标时,这个目标的引证计数就削减1,当引证计数为0的时分,就安全的开释它。

为了防止循环引证。需求自己控制在合适的位置运用 weak 引证。weak 引证不会添加引证计数(这是在C++11中。 在android中,strong引证 和 weak引证 的计数是分开保存的。当然原理共同。只看强引证)

下面的代码基本都在 system/core 目录下,本文中的代码来自android 13 。就不逐个具体标明了。

1、LightRefBase + sp

LightRefBase 是一个模板类,内部经过成员变量mCount来对引证进行计数,incStrong办法对mCount加1,decStrong办法对mCount减1。假如不涉及循环引证。直接承继类LightRefBase运用即可。

template <class T>
class LightRefBase
{
public:
    // 构造函数初始化引证计数为0
    inline LightRefBase() : mCount(0) { }
    // 引证计数变量加1
    inline void incStrong(__attribute__((unused)) const void* id) const {
        mCount.fetch_add(1, std::memory_order_relaxed);
    }
    // 引证计数减1
    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);
            // 当引证计数器减到0的时分经过del开释本来目标
            delete static_cast<const T*>(this);
        }
    }
    // 获取引证计数值
    inline int32_t getStrongCount() const {
        return mCount.load(std::memory_order_relaxed);
    }
    typedef LightRefBase<T> basetype;
protected:
    inline ~LightRefBase() { }
private:
    // 引证计数成员变量
    mutable std::atomic<int32_t> mCount;
};

sp是轻量级指针的完成类,一起也是强指针的完成类。构造函数+1,析构函数-1。

长处:简略便利,能掩盖大多数场景

缺陷:有循环引证导致无法开释,进而导致内存走漏问题。

template<typename T>
class sp {
public:
    inline sp() : m_ptr(nullptr) { }
    // The old way of using sp<> was like this. This is bad because it relies
    // on implicit conversion to sp<>, which we would like to remove (if an
    // object is being managed some other way, this is double-ownership). We
    // want to move away from this:
    //
    //     sp<Foo> foo = new Foo(...); // DO NOT DO THIS
    //
    // Instead, prefer to do this:
    //
    //     sp<Foo> foo = sp<Foo>::make(...); // DO THIS
    //
    // Sometimes, in order to use this, when a constructor is marked as private,
    // you may need to add this to your class:
    //
    //     friend class sp<Foo>;
    template <typename... Args>
    static inline sp<T> make(Args&&... args);
    // if nullptr, returns nullptr
    //
    // if a strong pointer is already available, this will retrieve it,
    // otherwise, this will abort
    static inline sp<T> fromExisting(T* other);
    // for more information about this macro and correct RefBase usage, see
    // the comment at the top of utils/RefBase.h
#if defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
    sp(std::nullptr_t) : sp() {}
#else
    sp(T* other);  // NOLINT(implicit)
    template <typename U>
    sp(U* other);  // NOLINT(implicit)
    sp& operator=(T* other);
    template <typename U>
    sp& operator=(U* other);
#endif
    sp(const sp<T>& other);
    sp(sp<T>&& other) noexcept;
    template<typename U> sp(const sp<U>& other);  // NOLINT(implicit)
    template<typename U> sp(sp<U>&& other);  // NOLINT(implicit)
    // Cast a strong pointer directly from one type to another. Constructors
    // allow changing types, but only if they are pointer-compatible. This does
    // a static_cast internally.
    template <typename U>
    static inline sp<T> cast(const sp<U>& other);
    ~sp();
    // Assignment
    sp& operator = (const sp<T>& other);
    sp& operator=(sp<T>&& other) noexcept;
    template<typename U> sp& operator = (const sp<U>& other);
    template<typename U> sp& operator = (sp<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; }
    // Punt these to the wp<> implementation.
    template<typename U>
    inline bool operator == (const wp<U>& o) const {
        return o == *this;
    }
    template<typename U>
    inline bool operator != (const wp<U>& o) const {
        return o != *this;
    }
private:
    template<typename Y> friend class sp;
    template<typename Y> friend class wp;
    void set_pointer(T* ptr);
    static inline void check_not_on_stack(const void* ptr);
    T* m_ptr;
};
template<typename T> template<typename U>
sp<T>::sp(const sp<U>& 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);
}

2、RefBase + wp + sp

RefBase 也是模板类,其间,强引证的计数,供给了incStrong和decStrong办法来保护;弱引证的计数供给了incWeak和decWeak办法。一起它运用weakref_type类的目标来描述目标的引证计数,该类完成类为weakref_impl。因而一起需求运用强指针或者弱指针(也便是要考虑内存走漏的或许状况),就需求承继类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);
        // 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); 
    }
protected:
    // When constructing these objects, prefer using sp::make<>. Using a RefBase
    // object on the stack or with other refcount mechanisms (e.g.
    // std::shared_ptr) is inherently wrong. RefBase types have an implicit
    // ownership model and cannot be safely used with other ownership models.
                            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;
};

wp是弱指针的完成类。为RefBase供给了弱引证计数,经过weakref_type指针类型的成员变量m_refs,用来保护目标的弱引证计数。

template <typename T>
class wp
{
public:
    typedef typename RefBase::weakref_type weakref_type;
    inline wp() : m_ptr(nullptr), m_refs(nullptr) { }
    // if nullptr, returns nullptr
    //
    // if a weak pointer is already available, this will retrieve it,
    // otherwise, this will abort
    static inline wp<T> 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 <typename U>
    wp(U* other);  // NOLINT(implicit)
    wp& operator=(T* other);
    template <typename U>
    wp& operator=(U* other);
#endif
    wp(const wp<T>& other);
    explicit wp(const sp<T>& other);
    template<typename U> wp(const sp<U>& other);  // NOLINT(implicit)
    template<typename U> wp(const wp<U>& other);  // NOLINT(implicit)
    ~wp();
    // Assignment
    wp& operator = (const wp<T>& other);
    wp& operator = (const sp<T>& 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_FUNCTIONAL(>, std::greater)
    COMPARE_WEAK_FUNCTIONAL(<, std::less)
    COMPARE_WEAK_FUNCTIONAL(<=, std::less_equal)
    COMPARE_WEAK_FUNCTIONAL(>=, std::greater_equal)
    template<typename U>
    inline bool operator == (const wp<U>& o) const {
        return m_refs == o.m_refs;  // Implies m_ptr == o.mptr; see invariants below.
    }
    template<typename U>
    inline bool operator == (const sp<U>& o) const {
        // Just comparing m_ptr fields is often dangerous, since wp<> may refer to an older
        // object at the same address.
        if (o == nullptr) {
          return m_ptr == nullptr;
        } else {
          return m_refs == o->getWeakRefs();  // Implies m_ptr == o.mptr.
        }
    }
    template<typename U>
    inline bool operator != (const sp<U>& o) const {
        return !(*this == o);
    }
    template<typename U>
    inline bool operator > (const wp<U>& o) const {
        if (m_ptr == o.m_ptr) {
            return _wp_compare_<std::greater>(m_refs, o.m_refs);
        } else {
            return _wp_compare_<std::greater>(m_ptr, o.m_ptr);
        }
    }
    template<typename U>
    inline bool operator < (const wp<U>& o) const {
        if (m_ptr == o.m_ptr) {
            return _wp_compare_<std::less>(m_refs, o.m_refs);
        } else {
            return _wp_compare_<std::less>(m_ptr, o.m_ptr);
        }
    }
    template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
    template<typename U> inline bool operator <= (const wp<U>& 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;
    T*              m_ptr;
    weakref_type*   m_refs;
};
template<typename T> template<typename U>
wp<T>::wp(const sp<U>& other)
    : m_ptr(other.m_ptr)
{
    m_refs = m_ptr ? m_ptr->createWeak(this) : nullptr;
}
template<typename T>
wp<T>::~wp()
{
    if (m_ptr) m_refs->decWeak(this);
}
template<typename T>
wp<T>& wp<T>::operator = (const wp<T>& other)
{
    weakref_type* otherRefs(other.m_refs);
    T* otherPtr(other.m_ptr);
    if (otherPtr) otherRefs->incWeak(this);
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = otherPtr;
    m_refs = otherRefs;
    return *this;
}
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;
}

wp并不能直接操作它引证的目标,是因为wp类并没有重载*和->操作符号,因而无法对wp经过*和->进行调用。那么在需求操作它所引证的目标的时分,需求运用wp的成员函数promote,其完成如下:

template<typename T>
// 弱指针进行升级为强指针
// promote回来sp类型就能够对其进行操作
sp<T> wp<T>::promote() const
{
    sp<T> result;
    // 实践上是经过weakref_impl的attemptIncStrong函数来检查该目标是否被开释
    if (m_ptr && m_refs->attemptIncStrong(&result)) {
        // 假如该目标有用,将m_ptr赋值到上面定义的sp类中
        result.set_pointer(m_ptr);
    }
    // 回来一个强引证,它指向的目标与该弱引证指向的目标是同一个目标
    return result;
}

3、Android中的实践运用场景

可 wp 的运用和JAVA中的回调运用相同。由于回调经常有或许生命周期比正常activity等要长,运用 wp 来引证能够削减内存走漏或许

class OpsCallback : public BnAppOpsCallback {
public:
    explicit OpsCallback(wp<BasicClient> client);
    virtual void opChanged(int32_t op, const String16& packageName);
private:
    wp<BasicClient> mClient;
}; // class OpsCallback
class BasicClient : public virtual RefBase {
    friend class CameraService;
    public:
        virtual status_t       initialize(sp<CameraProviderManager> manager,
                const String8& monitorTags) = 0;
        virtual binder::Status disconnect();
        // because we can't virtually inherit IInterface, which breaks
        // virtual inheritance
        virtual sp<IBinder>    asBinderWrapper() = 0;
        // Return the remote callback binder object (e.g. ICameraDeviceCallbacks)
        sp<IBinder>            getRemote() {
            return mRemoteBinder;
        }
        ...
        // these are initialized in the constructor.
        static sp<CameraService>        sCameraService;
        ...
}

其间 sp 的 CameraService 也承继了 RefBase 。

QSSI.13/frameworks/av/services/camera/libcameraservice/CameraService.h
class CameraService :
    public BinderService<CameraService>,
    public virtual ::android::hardware::BnCameraService,
    public virtual IBinder::DeathRecipient,
    public virtual CameraProviderManager::StatusListener
{
    friend class BinderService<CameraService>;
    friend class CameraOfflineSessionClient;
public:
...
}
QSSI.13/frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.h
struct StatusListener : virtual public RefBase {
        ~StatusListener() {}
        virtual void onDeviceStatusChanged(const String8 &cameraId,
                CameraDeviceStatus newStatus) = 0;
        virtual void onDeviceStatusChanged(const String8 &cameraId,
                const String8 &physicalCameraId,
                CameraDeviceStatus newStatus) = 0;
        virtual void onTorchStatusChanged(const String8 &cameraId,
                TorchModeStatus newStatus,
                SystemCameraKind kind) = 0;
        virtual void onTorchStatusChanged(const String8 &cameraId,
                TorchModeStatus newStatus) = 0;
        virtual void onNewProviderRegistered() = 0;
    };

而 LightRefBase 的运用在 CameraFlashlight 中有体现。

class CameraFlashlight : public virtual VirtualLightRefBase {
    public:
        CameraFlashlight(sp<CameraProviderManager> providerManager,
                CameraProviderManager::StatusListener* callbacks);
        virtual ~CameraFlashlight();
    ...
}
QSSI.13/frameworks/av/services/camera/libcameraservice/CameraService.h
// flashlight control
sp<CameraFlashlight> mFlashlight;