整理笔记

深入解析sp<T>与Thread类的使用及BootAnimation的原理
本文详细介绍了sp<T>类的管理引用计数机制,以及如何正确使用sp<T>和Thread类。同时,解释了BootAnimation类是如何通过SurfaceComposerClient获取屏幕显示参数并进行动画展示的。

1、sp指针
sp指针原型模板和构造函数如下:

template<typename T>

sp<T>::sp(const sp<T>& 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);

}


在构造函数中调用了incStrong(),在析构函数中调用的decStrong(),显然是管理引用计数的函数,但是sp类的中并没有定义这两个函数,

这两个函数是在RefBase类中定义的,由此可以得出结论:要想使用sp<T>或者wp<T>, T必需要继承RefBase类才行,在看RefBaseincStrong()

     voidRefBase::incStrong(const void* id) const

     {

             weakref_impl* const refs = mRefs;

             refs->incWeak(id);

            refs->addStrongRef(id);

             constint32_t c = android_atomic_inc(&refs->mStrong);

             ALOG_ASSERT(c > 0,"incStrong() called on %p after last strong ref", refs);

             #ifPRINT_REFS

                ALOGD("incStrongof %p from %p: cnt=%d\n", this, id, c);

              #endif

             if (c !=INITIAL_STRONG_VALUE)  {

                 return;

             }

             android_atomic_add(-INITIAL_STRONG_VALUE,&refs->mStrong);

             refs->mBase->onFirstRef();    //使用sp指针要继承与RefBase和实现OnFirstRef()

     }

 

     voidRefBase::decStrong(const void* id) const

     {

          weakref_impl* const refs = mRefs;

          refs->removeStrongRef(id);

          const int32_t c =android_atomic_dec(&refs->mStrong);  //T指针引用次数

          #ifPRINT_REFS

              ALOGD("decStrongof %p from %p: cnt=%d\n", this, id, c);

          #endif

          ALOG_ASSERT(c >= 1,"decStrong() called on %p too many times", refs);

          if (c == 1) {

             refs->mBase->onLastStrongRef(id);

             if ((refs->mFlags&OBJECT_LIFETIME_MASK)== OBJECT_LIFETIME_STRONG) {

                 delete this;   //如果是最后一个delete

             }

          }

          refs->decWeak(id);

     }


2、Thread类调用流程

使用方法:new Thread(bool flag).run("name", priority);

status_t Thread::run(const char* name, int32_tpriority, size_t stack)

{

   Mutex::Autolock _l(mLock);

 

    if(mRunning) {

        //thread already started

       return INVALID_OPERATION;

    }

   .........................

    mThread =thread_id_t(-1);

   //mCanCallJava在new时的flag

    if(mCanCallJava) {

        res =createThreadEtc(_threadLoop,

               this, name, priority, stack, &mThread);

    } else {

     /* 此函数中实现pthread_create(&thread,&attr,(android_pthread_entry)entryFunction, userData),此时

              entryFunction就是_threadLoop */

        res =androidCreateRawThreadEtc(_threadLoop,

               this, name, priority, stack, &mThread);

    }

   ........................

    returnNO_ERROR;

}

 

int Thread::_threadLoop(void* user)

{

    Thread*const self = static_cast<Thread*>(user);

    ........

    do {

        boolresult;

        if(first) {

           first = false;

            self->mStatus= self->readyToRun();

           result = (self->mStatus == NO_ERROR);

 

           if (result && !self->exitPending()) {

               result = self->threadLoop();

            }

        }else {

            result = self->threadLoop();

        }

       ...........

       strong.clear();

        //And immediately, re-acquire a strong reference for the next loop

       strong = weak.promote();

    }while(strong != 0);

   

    return 0;

}

所以Thread的使用要实现readyToRun()和threadLoop();


3、BootAnimation

BootAnimation::BootAnimation() : Thread(false)

{

    mSession= new SurfaceComposerClient();

}

SurfaceComposerClient::SurfaceComposerClient()

    : mStatus(NO_INIT),mComposer(Composer::getInstance())

{

}

Composer::getInstance()就是获取surfaceflinger服务Binder,mComposer就是surfaceflinger的代理;


在函数BootAnimation::readyToRun()中的SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)就是获取surfaceflinger类中成员:

mDefaultDisplays,而mDefaultDisplays[i] = new BBinder(),其中i为DisplayDevice::DisplayType,即mDefaultDisplays其实实质为Binder;

SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo)中到surfaceflinger的getDisplayInfo()的屏幕显示参数,从HWComposer中的mDisplayData获取,而HWComposer 在surfaceflinger的readyToRun()产生的对象;


待续。。。

### 回答1: Verdi培训整理笔记主要是指针对Verdi软件进行的培训所做的总结和整理。Verdi是一款用于设计验证和调试的仿真工具,广泛用于芯片设计和验证领域。培训整理笔记的目的是帮助学员系统化地掌握Verdi的使用方法和技巧,从而提高设计验证的效率和准确性。 Verdi培训整理笔记通常包括以下内容: 1. Verdi的基本介绍:包括Verdi的功能特点、应用领域等基本信息,以及如何正确安装和配置Verdi软件。 2. Verdi的基本操作:介绍Verdi的用户界面和基本元件,包括如何打开设计文件、添加信号和波形以及观察时序图等操作。 3. Verdi的高级功能:介绍Verdi的高级功能,如信号追踪、代码覆盖率分析、时序约束检查等。帮助学员深入理解Verdi的强大功能,并能在设计验证过程中灵活应用。 4. 常见问题和解决方法:整理常见的Verdi应用问题,并给出相应的解决方法。帮助学员能够快速解决在Verdi使用过程中遇到的问题。 总之,Verdi培训整理笔记是一个对Verdi软件进行系统性梳理和总结的过程,通过整理这些笔记,学员可以更好地理解和应用Verdi,提高设计验证的能力和效率。 ### 回答2: Verdi培训整理笔记是指对所接受的Verdi培训内容进行整理和总结的过程。通过整理笔记,我们可以更好地回顾和巩固自己所学的知识,提高学习效果和记忆力。下面将介绍整理笔记的重要性以及如何进行有效的Verdi培训整理笔记。 首先,整理笔记的重要性不可忽视。通过整理笔记,我们可以将繁杂的培训内容进行分类、梳理和归纳,帮助我们更好地理解和记忆知识点。同时,整理笔记也方便我们今后复习和回顾所学内容,提高知识的掌握和应用能力。此外,在工作中,整理笔记也是一种重要的信息管理方式,方便回顾和查阅。 进行Verdi培训整理笔记时,可以采取以下方法。首先,在培训过程中,要积极记录重要的概念、原理、公式等内容,尤其是讲解重点和难点的部分。其次,在整理笔记时可以使用标题、分点和箭头等方式使笔记结构清晰,便于理解和回顾。同时,可以使用不同颜色的笔或者高亮笔标记重点内容,突出重要性。另外,在整理过程中,可以加上个人理解和思考,以及实际应用的案例,丰富笔记内容,便于理解和记忆。 总结而言,Verdi培训整理笔记对于我们巩固所学知识、提高学习效果和提升工作能力都起到了重要作用。通过合理的整理笔记方法,我们可以更好地理解和记忆所学内容,并能在之后的学习和工作中随时回顾和查阅需要的知识点。因此,在接受培训过程中,要重视整理笔记的工作,培养良好的整理笔记习惯,提高学习效果和工作能力。 ### 回答3: Verdi培训整理笔记是指对Verdi培训内容进行整理和归纳的笔记。Verdi培训是一种针对软件开发工程师的培训课程,旨在提供关于Verdi工具的使用和调试技巧。在学习这门课程时,整理笔记是非常重要的,可以帮助我们梳理课程的重点和核心内容。 首先,在整理笔记时,我们可以按照不同的章节或主题进行分类,方便日后查找和复习。比如,可以按照Verdi工具的不同功能模块,如调试界面、波形查看、时序分析等进行分类。 其次,在整理笔记时,应该注意抓住重点和关键信息。Verdi培训课程通常涉及到很多细节和技术性的知识,我们应该将重点内容标记出来,例如重要的Verdi命令和快捷键,以及常用的调试方法和技巧。 此外,笔记应该简明扼要,避免冗长的叙述和重复的内容。我们可以使用清晰简洁的语言记录下关键信息和思路,以便后期复习时快速回顾。 最后,在整理笔记时,可以结合自己的理解和总结,对所学内容进行概括和归纳。这不仅有助于加深对Verdi工具的理解,还可以为今后实践应用提供参考。 总之,Verdi培训整理笔记是一项重要的学习工作,它可以帮助我们更好地掌握Verdi工具的使用技巧和调试方法。通过合理整理和归纳,我们可以在日后的实践中更加高效地应用Verdi工具,提升我们的工作效率和质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值