Marco de trabajo de Android RefBase,sp,wp

ubicación del código

android-12.0.0_r28/system/core/libutils/include/utils/RefBase.h

android-12.0.0_r28/system/core/libutils/RefBase.cpp

android-12.0.0_r28/system/core/libutils/include/utils/StrongPointer.h

Ejemplo de uso

#include <utils/RefBase.h>
using namespace android;
class MyClass : public RefBase {
public:
    MyClass() { printf("MyClass created\n"); }
    virtual ~MyClass() { printf("MyClass destroyed\n"); }
    virtual void onFirstRef() { printf("MyClass onFirstRef\n"); }
    virtual void onLastStrongRef(const void* id) { printf("MyClass onLastStrongRef\n"); }
};

int main(){
	MyClass* myClass = new MyClass();
	myClass->incStrong(myClass);
	myClass->decStrong(myClass);
    
    MyClass* myClass1 = new MyClass();
    sp<MyClass> spClass = myClass1;
    wp<MyClass> wpClass = myClass1;
    sp<MyClass> spClassFromwp = wpClass.promote();
	if (spClassFromwp == NULL) {
		printf("spClassFromwp is NULL\n");
	}
	return 0;
}

Introducción

base de referencia

  • Proporcione un mecanismo de conteo de referencias de objetos: cada objeto heredado de RefBase tendrá un contador de referencias para registrar la cantidad de veces que se hace referencia al objeto. Cuando el contador de referencia llega a 0, el objeto se libera automáticamente.
  • Proporcionar un mecanismo de administración de memoria de objetos: a través de la clase RefBase, podemos administrar mejor el uso de memoria de los objetos, lo que reduce la ocurrencia de pérdidas de memoria y errores OOM.
  • Proporcione seguridad de subprocesos: el uso de RefBase puede garantizar la seguridad de subprocesos del objeto y evitar la competencia y los conflictos durante el acceso de subprocesos múltiples.

En la implementación de RefBase, incluye principalmente las siguientes funciones miembro:

  • incStrong: Incrementa el conteo de referencia del objeto.
  • decStrong: Disminuye el recuento de referencias del objeto.
  • extendObjectLifetime: Ampliar la vida útil del objeto.
  • onFirstRef: se llama cuando se hace referencia al objeto por primera vez
  • onLastStrongRef: llamado cuando se libera la última referencia fuerte al objeto
  • onLastWeakRef: En OBJECT_LIFETIME_WEAKcaso de que se llame cuando finalice la última referencia.

clase de plantilla sp

  • Proporcione un mecanismo de conteo de referencia de objetos: a través de sp, podemos administrar el conteo de referencia de objetos de manera más conveniente, evitando así el problema tedioso y propenso a errores de la administración manual del conteo de referencia.
  • Proporcionar un mecanismo de administración de memoria de objetos: a través de sp, podemos administrar mejor el uso de memoria de los objetos y evitar pérdidas de memoria y errores OOM.
  • Proporcione seguridad de subprocesos: el uso de sp puede garantizar la seguridad de subprocesos del objeto y evitar la competencia y el conflicto durante el acceso de subprocesos múltiples.

En la implementación de sp, incluye principalmente las siguientes funciones miembro:

  • sp: Constructor, utilizado para crear objetos sp.
  • get: Obtener el puntero del objeto gestionado por sp.
  • clear: borre el puntero administrado por el objeto sp y disminuya el recuento de referencia en uno.
  • operator->: se utiliza para implementar operaciones de acceso de puntero y puede acceder fácilmente a funciones miembro y variables miembro de objetos administrados por sp.
  • operator bool: Se utiliza para juzgar si el objeto sp está vacío, es decir, si el puntero administrado es NULL.

clase de plantilla wp

  • Proporcione un mecanismo de conteo de referencias de objetos: a través de wp, podemos administrar el conteo de referencias de objetos de manera más conveniente, evitando los problemas tediosos y propensos a errores de administrar manualmente el conteo de referencias.
  • Evite las referencias circulares y las fugas de memoria: Dado que wp no aumenta el número de referencias de los objetos, puede evitar los problemas de las referencias circulares y las fugas de memoria.
  • Proporcione almacenamiento en caché de objetos y control de acceso: el uso de wp puede ayudar a los desarrolladores a administrar mejor el almacenamiento en caché de objetos y el control de acceso, mejorando así el rendimiento y la estabilidad del sistema.

En la implementación de wp, incluye principalmente las siguientes funciones miembro:

  • wp: Constructor, utilizado para crear objetos wp.
  • promote: Actualice el objeto administrado por wp al objeto sp.
  • clear: Limpia el puntero administrado por el objeto wp.

Implementación del código fuente

base de referencia

class RefBase
{
// ...

protected:
    RefBase();
private:
    weakref_impl* const mRefs;
// ...
};

Los derechos de acceso todavía están allí protected, por lo que significa que RefBaseesta clase solo se puede usar como clase base.

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

RefBase::~RefBase()
{
    int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
    。。。//注释
    if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
        // It's possible that the weak count is not 0 if the object
        // re-acquired a weak reference in its destructor
        if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
            // 释放记录引用计数的对象mRefs(weakref_impl类)
            delete mRefs;
        }
    } else {
        。。。//一些注释和打印
    }
    // 置空记录引用计数的对象mRefs(weakref_impl类)
    const_cast<weakref_impl*&>(mRefs) = nullptr;
}

RefBaseConstructor, solo se inicializa su mRefspuntero y se inicializa como weakref_implobjeto.

class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
    std::atomic<int32_t>    mStrong;
    std::atomic<int32_t>    mWeak;
    RefBase* const          mBase;
    std::atomic<int32_t>    mFlags;
...
    explicit weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE)
        , mWeak(0)
        , mBase(base)
        , mFlags(OBJECT_LIFETIME_STRONG)
    {
    }
...
}

mStrong: Representa un fuerte conteo de referencias, el valor inicial esINITIAL_STRONG_VALUE = 1<<28

mWeak: Representa un conteo de referencia débil

mBase: apunta al objeto de clase RefBasederivado

mFlags: representa el ciclo de vida de los objetos de clase RefBasederivados

1. RefBase crea la clase débilref_impl para registrar la situación de conteo

2. Inicialice el recuento de referencia fuerte como INITIAL_STRONG_VALUE, el recuento de referencia débil como 0 y el ciclo de vida de referencia fuerte predeterminado

//! Flags for extendObjectLifetime() 可以用extendObjectLifetime方法设置
	enum {
        OBJECT_LIFETIME_STRONG  = 0x0000,// 强引用生命周期
        OBJECT_LIFETIME_WEAK    = 0x0001,// 弱引用生命周期
        OBJECT_LIFETIME_MASK    = 0x0001 // 掩码,屏蔽或过滤二进制数据中的特定位
    };
Funciones de conteo de referencia fuerte: incStrong, decStrong
void RefBase::incStrong(const void* id) const
{
    weakref_impl* const refs = mRefs; //mRefs就是RefBase在构造函数传进去的weakref_impl对象
    refs->incWeak(id);//弱引用增加,看下incWeak分析

    refs->addStrongRef(id);//空实现,用作调试,重点看宏定义DEBUG_REFS的开关
    //原子操作(保证多线程安全),记录强引用说计数mStrong,增加1,返回旧值,此时c=INITIAL_STRONG_VALUE。
    const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
    ....
    //如果强引用的旧值,不等于初始值INITIAL_STRONG_VALUE,那么代表现在的强引用计数为1,或2,或3,等等
    if (c != INITIAL_STRONG_VALUE)  {
        //直接return 掉,防止一直回调下面的onFirstRef()
        return;
    }

    ...
	//当首次增加强引用时,原子操作mStrong.fetch_sub时,mStrong = mStrong - INITIAL_STRONG_VALUE = 1;
    int32_t old __unused = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE, std::memory_order_relaxed);
    ....
    //调用成员函数onFirstRef(如果派生类有重写该类,则会调用子类的onFirstRef)
    refs->mBase->onFirstRef();
}

void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id);//空实现,用作调试,重点看宏定义DEBUG_REFS的开关
    //原子操作(保证多线程安全),记录强引用mStrong计数,减阖1,返回旧值
    const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);
    ...
    //当强引用计数mStrong旧值为1时
    if (c == 1) {
        std::atomic_thread_fence(std::memory_order_acquire);
        //调用成员函数onLastStrongRef
        refs->mBase->onLastStrongRef(id);
        int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            //强引用生命周期(默认)时,释放RefBase对象(RefBase的派生类)
            delete this;
            // The destructor does not delete refs in this case.
        }
    }
    ...
    refs->decWeak(id);//弱引用减少,decWeak
}

incStrongIncrementa el conteo de referencia fuerte, y la primera vez que se incrementa (es decir, se llama cuando se hace referencia al objeto por primera vez), la devolución de llamadaonFirstRef

decStrongDisminuye el conteo de referencias seguras y cuando se redujo por última vez (es decir, se llama cuando se libera la última referencia fuerte al objeto), la devolución de llamadaonLastStrongRef

Funciones de conteo de referencia débiles: incWeak, decWeak
void RefBase::weakref_type::incWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->addWeakRef(id);//空实现,重点看宏定义DEBUG_REFS的开关,用作调试
    //原子操作(保证多线程安全),记录弱引用mWeak计数,增加1,返回旧值
    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);
}

void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id);//空实现,重点看宏定义DEBUG_REFS的开关,用作调试
    //原子操作(保证多线程安全),记录弱引用mWeak计数,减去1,返回旧值
    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);
    //条件1:如果是强引用生命周期(默认) 
    if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
        ....//一些注释
        //条件2:强引用计数mStrong不等于初始值INITIAL_STRONG_VALUE
        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 {
            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
            //则释放记录引用计数的对象mRefs(weakref_impl)
            delete impl;
        }
    } else {
        // This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
        // is gone, we can destroy the object.
        // 弱引用生命周期
        // 回调成员函数onLastWeakRef,并释放RefBase对象(派生类)
        impl->mBase->onLastWeakRef(id);
        delete impl->mBase;
    }
}

1. La función de aumento del conteo de referencia fuerte incStrong()->incWeak(), además del conteo de referencia fuerte mStrongmás 1, el conteo de referencia débil también agregará 1 a mWeak

2. La función de aumento del conteo de referencia débil solo agregará 1 decWeak()al conteo de referencia débil solomWeak

Fuerte ciclo de vida de referencia Ciclo de vida de referencia débil
El conteo de referencia fuerte mStrong es 0 RefBaseobjeto de clase derivado liberado ninguno
El conteo de referencia débil mWeak es 0 Cuando el recuento de referencia fuerte no es el valor inicial, suelte el objeto que registra el recuento de referenciamRefs(weakref_impl类) soltar RefBaseobjeto y mRefs(weakref_impl类)objeto

pseudocódigo

decStrong(){
	1、delete this; // 即释放RefBase的派生类对象,mStrong=0
	2、refs->decWeak(id) {
        //强引用生命周期
		if(mStrong !=INITIAL_STRONG_VALUE){
			delete impl; //当强引用计数非初始值时,释放mRefs(weakref_impl,负责记录引用计数的类)对象,mWeak=0
		}else{
            //弱引用生命周期
            //释放RefBase的派生类对象,调用RefBase的析构函数(调用delete mRefs:释放记录引用计数的对象mRefs(weakref_impl类))
            delete impl->mBase; 
        }	
	}
}

3. Cuando RefBaseel objeto de la clase derivada está bajo el ciclo de vida de referencia fuerte, la memoria dinámica del objeto de la clase derivada de RefBase se liberará solo cuando el recuento de referencia fuerte sea 0.

4. Cuando RefBaseel objeto de la clase derivada está bajo el ciclo de vida de referencia débil, la memoria dinámica del objeto de la clase derivada de RefBase se liberará solo cuando el recuento de referencia débil sea 0.

clase de plantilla sp

//构造函数
template<typename T>
sp<T>::sp(T* other)
        : m_ptr(other) {
    if (other) {
        check_not_on_stack(other);
     /* 调用RefBase类的incStrong函数:强引用计数mStrong加1,弱引用计数mWeak加1
     * 此时mStrong = 1,mWeak = 1.首次增加强引用计数,回调RefBase类成员函数onFirstRef
     */
        other->incStrong(this);
    }
}            
            

//析构函数
template<typename T>
sp<T>::~sp() {
    if (m_ptr) {
    /* 调用RefBase类的decStrong函数:强引用计数mStrong减1,弱引用计数mWeak减1
     * 此时mStrong = 0,mWeak = 0.强引用计数为0,回调RefBase类成员函数onLastStrongRef并释放RefBase对象.弱引用计数为0,释放mRefs对象
     */
   	    m_ptr->decStrong(this);
    }
}

1. Al comienzo del ciclo de vida: el constructor llama a la función incStrong del objeto RefBase asociado (el recuento de referencias fuertes y débiles más 1) 2. Al final del ciclo de vida: el destructor llama a la función decStrong del objeto
asociado Objeto RefBase (el recuento de referencia fuerte y débil menos 1))

clase de plantilla wp

//构造函数
template<typename T>
wp<T>::wp(T* other)
    : m_ptr(other)
{
    m_refs = other ? m_refs = other->createWeak(this) : nullptr;
}

RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
    mRefs->incWeak(id);	/* 弱引用计数加1,此时mWeak = 1 */
    return mRefs;	/* 返回记录引用计数对象mRefs */
}

//析构函数
template<typename T>
wp<T>::~wp()
{
    if (m_ptr) m_refs->decWeak(this); /* 弱引用计数减1,此时mWeak = 0,释放mRefs对象 */
}

//promote函数
template<typename T>
sp<T> wp<T>::promote() const
{
    sp<T> result;
    //判断wp<T>指向的引用m_ptr(T* m_ptr)是否被释放了,如果没有的话,将执行m_refs->attemptIncStrong(&result)
    if (m_ptr && m_refs->attemptIncStrong(&result)) {
        result.set_pointer(m_ptr);
    }
    return result;
}

//attemptIncStrong:主要逻辑就是判断该对象是不是已经回收了,实际上只要是该对象没有被回收,那么都是可以被提升到强指针
bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
    //弱引用计数mWeak加1	
    incWeak(id);

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

    ...
	//强引用计数mStrong大于0且不为初始值时
    while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
        ...//注释
        // 只有mStrong的值为curCount时,才会将其值修改为curCount + 1, return true,否则修改失败,return false。    
        if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                std::memory_order_relaxed)) {
            break;
        }
        ...//注释
    }
	//之前强引用计数为0,或者为初始值
    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
        // we're now in the harder case of either:
        // - there never was a strong reference on us
        // - or, all strong references have been released
        int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
        //强引用生命周期时
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            // this object has a "normal" life-time, i.e.: it gets destroyed
            // when the last strong reference goes away
            //如果强引用计数mStrong小于等于0
            if (curCount <= 0) {
                // the last strong-reference got released, the object cannot
                // be revived.
                //因此对弱引用计数mWeak减1(对应开头加1)并返回false
                decWeak(id);
                return false;
            }

            // here, curCount == INITIAL_STRONG_VALUE, which means
            // there never was a strong-reference, so we can try to
            // promote this object; we need to do that atomically.
            while (curCount > 0) {
                if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                        std::memory_order_relaxed)) {
                    break;
                }
                // the strong count has changed on us, we need to re-assert our
                // situation (e.g.: another thread has inc/decStrong'ed us)
                // curCount has been updated.
            }

            if (curCount <= 0) {
                // promote() failed, some other thread destroyed us in the
                // meantime (i.e.: strong count reached zero).
                decWeak(id);
                return false;
            }
        } else {
            // this object has an "extended" life-time, i.e.: it can be
            // revived from a weak-reference only.
            // Ask the object's implementation if it agrees to be revived
            if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
                // it didn't so give-up.
                decWeak(id);
                return false;
            }
            // grab a strong-reference, which is always safe due to the
            // extended life-time.
            //弱生命周期时,mStrong加1并返回
            curCount = impl->mStrong.fetch_add(1, std::memory_order_relaxed);
            // If the strong reference count has already been incremented by
            // someone else, the implementor of onIncStrongAttempted() is holding
            // an unneeded reference.  So call onLastStrongRef() here to remove it.
            // (No, this is not pretty.)  Note that we MUST NOT do this if we
            // are in fact acquiring the first reference.
            if (curCount != 0 && curCount != INITIAL_STRONG_VALUE) {
                //回调onLastStrongRef
                impl->mBase->onLastStrongRef(id);
            }
        }
    }

    impl->addStrongRef(id);//空实现,重点看宏定义DEBUG_REFS的开关,用作调试

#if PRINT_REFS
    ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
#endif

    // curCount is the value of mStrong before we incremented it.
    // Now we need to fix-up the count if it was INITIAL_STRONG_VALUE.
    // This must be done safely, i.e.: handle the case where several threads
    // were here in attemptIncStrong().
    // curCount > INITIAL_STRONG_VALUE is OK, and can happen if we're doing
    // this in the middle of another incStrong.  The subtraction is handled
    // by the thread that started with INITIAL_STRONG_VALUE.
    if (curCount == INITIAL_STRONG_VALUE) {
        impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
                std::memory_order_relaxed);
    }

    return true;
}

1. Al principio del ciclo de vida: el constructor llama a la función del RefBaseobjeto asociado (recuento débil de referencias más 1 y devuelve el objeto mRefs) createWeak
2. Al final del ciclo de vida: el destructor llama a la función mRefsdel objeto asociado objeto decWeak(recuento de referencia débil menos 1)
3. Cuando desee utilizar el objeto asociado, debe llamar wpa la función miembro promotepara obtener spel objeto y sphacer un juicio no vacío sobre el objeto.

Supongo que te gusta

Origin blog.csdn.net/weixin_45767368/article/details/129263263
Recomendado
Clasificación