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;
}