> 文章列表 > Android系统之onFirstRef自动调用原理

Android系统之onFirstRef自动调用原理

Android系统之onFirstRef自动调用原理

前言:抽丝剥茧探究onFirstRef究竟为何在初始化sp<xxx>第一个调用?

1.onFirstRef调用位置

<1>.system/core/libutils/RefBase.cpp

#include <utils/RefBase.h>//1.初始化强指针
void RefBase::incStrong(const void* id) const
{weakref_impl* const refs = mRefs;refs->incWeak(id);refs->addStrongRef(id);const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);refs->mBase->onFirstRef();//调用onFirstRef
}//2.weakref_impl类
class RefBase::weakref_impl : public RefBase::weakref_type
{public:RefBase* const  mBase; //RefBase定义全局变量mBase.
};

RefBase基类中定义调用onFirstRef(),如果有实例化sp<T> ttt = new Test()后,将会自动调用onFirstRef()函数

<2>.system/core/libutils/RefBase.cpp

void RefBase::decStrong(const void* id) const
{weakref_impl* const refs = mRefs;refs->removeStrongRef(id);const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);//在调用析构函数时,自动调用onLastStrongRef()函数。refs->mBase->onLastStrongRef(id);}refs->decWeak(id);
}

在sp<T>的析构函数时,会自动调用onLastStrongRef();

2.onFirstRef定义位置

<1>.system/core/libutils/include/utils/RefBase.h

#include <utils/LightRefBase.h>
#include <utils/StrongPointer.h>class RefBase{protected:// Invoked after creation of initial strong pointer/reference.virtual void     onFirstRef();//定义虚函数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);//定义onLastStrongRefprivate:weakref_impl* const mRefs;};

在RefBase中定义虚函数onFirstRef()、onLastStrongRef()、以及weakref_impl类。

3.sp<T>实现位置

<1>.system/core/libutils/include/utils/StrongPointer.h

sp<T>构造函数

template<typename T>
sp<T>::sp(const sp<T>& other): m_ptr(other.m_ptr) {if (m_ptr)m_ptr->incStrong(this);
}

StrongPointer.h头文件中才是真正定义sp<T>智能指针的强指针的出处。

~sp<T>析构函数

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

4.Test onFirstRef Sample

写了一个sample帮助理解RefBase结构的onFirstRef原理。

<1>.Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)LOCAL_SRC_FILES := main.cpp
LOCAL_SHARED_LIBRARIES := libcutils libutils liblog libbaseLOCAL_MODULE := test_onfirstRef
include $(BUILD_EXECUTABLE)

<2>.main.cpp

#define LOG_TAG "Main"#include <utils/Log.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>//using namespace android;/*
1.system/core/libutils/include/utils/RefBase.hclass RefBase{protected:// Invoked after creation of initial strong pointer/reference.virtual void            onFirstRef();};2.system/core/libutils/include/utils/Threads.hclass Thread : virtual public RefBase{public:virtual status_t run(const char* name,int32_t priority = PRIORITY_DEFAULT, size_t stack = 0);private:virtual bool threadLoop() = 0;};3.system/core/libutils/Threads.cppstatus_t Thread::run(const char* name, int32_t priority, size_t stack){res = androidCreateRawThreadEtc(_threadLoop,this, name, priority, stack, &mThread);}
*/class Test: public android::RefBase {
public:// Test(int id, char *name){//   printf("xxx------->%s(), line = %d, id = %d, name = %s\\n",__FUNCTION__,__LINE__,id,name);// }void onFirstRef(){printf("xxx------->%s(), line = %d\\n",__FUNCTION__,__LINE__);}void onLastStrongRef(__unused const void* id){printf("xxx------->%s(), line = %d\\n",__FUNCTION__,__LINE__);}bool onIncStrongAttempted(__unused uint32_t flags, __unused const void* id){printf("xxx------->%s(), line = %d\\n",__FUNCTION__,__LINE__);return true;}void onLastWeakRef(__unused const void* id){printf("xxx------->%s(), line = %d\\n",__FUNCTION__,__LINE__);}
};void print(android::sp<Test> tt){printf("xxx------------->%s(), line = %d, strong_count = %d\\n",__FUNCTION__,__LINE__,tt->getStrongCount());
}int main(){//char name[] = "onFirstRef";//1.没有调用onFirstRef//new Test(1234, name);//2.sp强智能指针自动调用onFirstRefandroid::sp<Test>  test = new Test(); //invoke onFirstRef() and onLastStrongRef().printf("xxx------------->%s(), line = %d, strong_count = %d\\n",__FUNCTION__,__LINE__,test->getStrongCount());//3.wp弱智能指针// android::wp<Test> wp_test = new Test();// android::sp<Test> sp_test =  wp_test.promote(); // invoke onLastStrongRef()// printf("xxx------------->%s(), line = %d, strong_count = %d\\n",__FUNCTION__,__LINE__,sp_test->getStrongCount());//4.将普通引用修改为常引用,为了避免函数使用时,防止test对象被修改.const android::sp<Test>  &test = new Test(); //invoke onFirstRef() and onLastStrongRef().//android::sp<Test>  &test = new Test(); //编译报错printf("xxx------------->%s(), line = %d, strong_count = %d\\n",__FUNCTION__,__LINE__,test->getStrongCount());print(new Test());return 0;
}