首页 文章 精选 留言 我的

精选列表

搜索[系统],共10000篇文章
优秀的个人博客,低调大师

Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析(4)

回到外层的if语句中,如果目标对象的生命周期是受弱引用计数控制的,就执行下面语句: impl->mBase->onLastWeakRef(id); if((impl->mFlags&OBJECT_LIFETIME_FOREVER)!=OBJECT_LIFETIME_FOREVER){ deleteimpl->mBase; } 理论上说,如果目标对象的生命周期是受弱引用计数控制的,那么当强引用计数和弱引用计数都为0的时候,这时候就应该delete目标对象了,但是这里还有另外一层控制,我们可以设置目标对象的标志值为OBJECT_LIFETIME_FOREVER,即目标对象的生命周期完全不受强引用计数和弱引用计数控制,在这种情况下,即使目标对象的强引用计数和弱引用计数都同时为0,这里也不能delete这个目标对象,那么,由谁来delete掉呢?当然是谁new出来的,就谁来delete掉了,这时候智能指针就完全退化为普通指针了,这里的智能指针设计的非常强大。 分析到这里,有必要小结一下: A. 如果对象的标志位被设置为0,那么只要发现对象的强引用计数值为0,那就会自动delete掉这个对象; B. 如果对象的标志位被设置为OBJECT_LIFETIME_WEAK,那么只有当对象的强引用计数和弱引用计数都为0的时候,才会自动delete掉这个对象; C. 如果对象的标志位被设置为OBJECT_LIFETIME_FOREVER,那么对象就永远不会自动被delete掉,谁new出来的对象谁来delete掉。 到了这里,强指针就分析完成了,最后来分析弱指针。 4. 弱指针 弱指针所使用的引用计数类与强指针一样,都是RefBase类,因此,这里就不再重复介绍了,我们直接来弱指针的实现,它定义在frameworks/base/include/utils/RefBase.h文件中: template<typenameT> classwp { public: typedeftypenameRefBase::weakref_typeweakref_type; inlinewp():m_ptr(0){} wp(T*other); wp(constwp<T>&other); wp(constsp<T>&other); template<typenameU>wp(U*other); template<typenameU>wp(constsp<U>&other); template<typenameU>wp(constwp<U>&other); ~wp(); //Assignment wp&operator=(T*other); wp&operator=(constwp<T>&other); wp&operator=(constsp<T>&other); template<typenameU>wp&operator=(U*other); template<typenameU>wp&operator=(constwp<U>&other); template<typenameU>wp&operator=(constsp<U>&other); voidset_object_and_refs(T*other,weakref_type*refs); //promotiontosp sp<T>promote()const; //Reset voidclear(); //Accessors inlineweakref_type*get_refs()const{returnm_refs;} inlineT*unsafe_get()const{returnm_ptr;} //Operators COMPARE_WEAK(==) COMPARE_WEAK(!=) COMPARE_WEAK(>) COMPARE_WEAK(<) COMPARE_WEAK(<=) COMPARE_WEAK(>=) inlinebooloperator==(constwp<T>&o)const{ return(m_ptr==o.m_ptr)&&(m_refs==o.m_refs); } template<typenameU> inlinebooloperator==(constwp<U>&o)const{ returnm_ptr==o.m_ptr; } inlinebooloperator>(constwp<T>&o)const{ return(m_ptr==o.m_ptr)?(m_refs>o.m_refs):(m_ptr>o.m_ptr); } template<typenameU> inlinebooloperator>(constwp<U>&o)const{ return(m_ptr==o.m_ptr)?(m_refs>o.m_refs):(m_ptr>o.m_ptr); } inlinebooloperator<(constwp<T>&o)const{ return(m_ptr==o.m_ptr)?(m_refs<o.m_refs):(m_ptr<o.m_ptr); } template<typenameU> inlinebooloperator<(constwp<U>&o)const{ return(m_ptr==o.m_ptr)?(m_refs<o.m_refs):(m_ptr<o.m_ptr); } inlinebooloperator!=(constwp<T>&o)const{returnm_refs!=o.m_refs;} template<typenameU>inlinebooloperator!=(constwp<U>&o)const{return!operator==(o);} inlinebooloperator<=(constwp<T>&o)const{return!operator>(o);} template<typenameU>inlinebooloperator<=(constwp<U>&o)const{return!operator>(o);} inlinebooloperator>=(constwp<T>&o)const{return!operator<(o);} template<typenameU>inlinebooloperator>=(constwp<U>&o)const{return!operator<(o);} private: template<typenameY>friendclasssp; template<typenameY>friendclasswp; T*m_ptr; weakref_type*m_refs; }; 与强指针类相比,它们都有一个成员变量m_ptr指向目标对象,但是弱指针还有一个额外的成员变量m_refs,它的类型是weakref_type指针,下面我们分析弱指针的构造函数时再看看它是如果初始化的。这里我们需要关注的仍然是弱指针的构造函数和析构函数。 先来看构造函数: template<typenameT> wp<T>::wp(T*other) :m_ptr(other) { if(other)m_refs=other->createWeak(this); } 这里的参数other一定是继承了RefBase类,因此,这里调用了RefBase类的createWeak函数,它定义在frameworks/base/libs/utils/RefBase.cpp文件中: RefBase::weakref_type*RefBase::createWeak(constvoid*id)const { mRefs->incWeak(id); returnmRefs; } 这里的成员变量mRefs的类型为weakref_impl指针,weakref_impl类的incWeak函数我们在前面已经看过了,它的作用就是增加对象的弱引用计数。函数最后返回mRefs,于是,弱指针对象的成员变量m_refs就指向目标对象的weakref_impl对象了。 再来看析构函数: template<typenameT> wp<T>::~wp() { if(m_ptr)m_refs->decWeak(this); } 这里,弱指针在析构的时候,与强指针析构不一样,它直接就调用目标对象的weakref_impl对象的decWeak函数来减少弱引用计数了,当弱引用计数为0的时候,就会根据在目标对象的标志位(0、OBJECT_LIFETIME_WEAK或者OBJECT_LIFETIME_FOREVER)来决定是否要delete目标对象,前面我们已经介绍过了,这里就不再介绍了。 分析到这里,弱指针还没介绍完,它最重要的特性我们还没有分析到。前面我们说过,弱指针的最大特点是它不能直接操作目标对象,这是怎么样做到的呢?秘密就在于弱指针类没有重载*和->操作符号,而强指针重载了这两个操作符号。但是,如果我们要操作目标对象,应该怎么办呢,这就要把弱指针升级为强指针了: template<typenameT> sp<T>wp<T>::promote()const { returnsp<T>(m_ptr,m_refs); } 升级的方式就使用成员变量m_ptr和m_refs来构造一个强指针sp,这里的m_ptr为指目标对象的一个指针,而m_refs则是指向目标对象里面的weakref_impl对象。 我们再来看看这个强指针的构造过程: template<typenameT> sp<T>::sp(T*p,weakref_type*refs) :m_ptr((p&&refs->attemptIncStrong(this))?p:0) { } 主要就是初始化指向目标对象的成员变量m_ptr了,如果目标对象还存在,这个m_ptr就指向目标对象,如果目标对象已经不存在,m_ptr就为NULL,升级成功与否就要看refs->attemptIncStrong函数的返回结果了: boolRefBase::weakref_type::attemptIncStrong(constvoid*id) { incWeak(id); weakref_impl*constimpl=static_cast<weakref_impl*>(this); int32_tcurCount=impl->mStrong; LOG_ASSERT(curCount>=0,"attemptIncStrongcalledon%pafterunderflow", this); while(curCount>0&&curCount!=INITIAL_STRONG_VALUE){ if(android_atomic_cmpxchg(curCount,curCount+1,&impl->mStrong)==0){ break; } curCount=impl->mStrong; } if(curCount<=0||curCount==INITIAL_STRONG_VALUE){ boolallow; if(curCount==INITIAL_STRONG_VALUE){ //Attemptingtoacquirefirststrongreference...thisisallowed //iftheobjectdoesNOThavealongerlifetime(meaningthe //implementationdoesn'tneedtoseethis),oriftheimplementation //allowsittohappen. allow=(impl->mFlags&OBJECT_LIFETIME_WEAK)!=OBJECT_LIFETIME_WEAK ||impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG,id); }else{ //Attemptingtorevivetheobject...thisisallowed //iftheobjectDOEShavealongerlifetime(sowecansafely //calltheobjectwithonlyaweakref)andtheimplementation //allowsittohappen. allow=(impl->mFlags&OBJECT_LIFETIME_WEAK)==OBJECT_LIFETIME_WEAK &&impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG,id); } if(!allow){ decWeak(id); returnfalse; } curCount=android_atomic_inc(&impl->mStrong); //Ifthestrongreferencecounthasalreadybeenincrementedby //someoneelse,theimplementorofonIncStrongAttempted()isholding //anunneededreference.SocallonLastStrongRef()heretoremoveit. //(No,thisisnotpretty.)NotethatweMUSTNOTdothisifwe //areinfactacquiringthefirstreference. if(curCount>0&&curCount<INITIAL_STRONG_VALUE){ impl->mBase->onLastStrongRef(id); } } impl->addWeakRef(id); impl->addStrongRef(id); #ifPRINT_REFS LOGD("attemptIncStrongof%pfrom%p:cnt=%d\n",this,id,curCount); #endif if(curCount==INITIAL_STRONG_VALUE){ android_atomic_add(-INITIAL_STRONG_VALUE,&impl->mStrong); impl->mBase->onFirstRef(); } returntrue; } 这个函数的作用是试图增加目标对象的强引用计数,但是有可能会失败,失败的原因可能是因为目标对象已经被delete掉了,或者是其它的原因,下面会分析到。前面我们在讨论强指针的时候说到,增加目标对象的强引用计数的同时,也会增加目标对象的弱引用计数,因此,函数在开始的地方首先就是调用incWeak函数来先增加目标对象的引用计数,如果后面试图增加目标对象的强引用计数失败时,会调用decWeak函数来回滚前面的incWeak操作。 这里试图增加目标对象的强引用计数时,分两种情况讨论,一种情况是此时目标对象正在被其它强指针引用,即它的强引用计数大于0,并且不等于INITIAL_STRONG_VALUE,另一种情况是此时目标对象没有被任何强指针引用,即它的强引用计数小于等于0,或者等于INITIAL_STRONG_VALUE。 第一种情况比较简单,因为这时候说明目标对象一定存在,因此,是可以将这个弱指针提升为强指针的,在这种情况下,只要简单地增加目标对象的强引用计数值就行了: while(curCount>0&&curCount!=INITIAL_STRONG_VALUE){ if(android_atomic_cmpxchg(curCount,curCount+1,&impl->mStrong)==0){ break; } curCount=impl->mStrong; } 当我们在这里对目标对象的强引用计数执行加1操作时,要保证原子性,因为其它地方也有可能正在对这个目标对象的强引用计数执行加1的操作,前面我们一般是调用android_atomic_inc函数来完成,但是这里是通过调用android_atomic_cmpxchg函数来完成,android_atomic_cmpxchg函数是体系结构相关的函数,在提供了一些特殊的指令的体系结构上,调用android_atomic_cmpxchg函数来执行加1操作的效率会比调用android_atomic_inc函数更高一些。函数android_atomic_cmpxchg是在system/core/include/cutils/atomic.h文件中定义的一个宏: intandroid_atomic_release_cas(int32_toldvalue,int32_tnewvalue, volatileint32_t*addr); #defineandroid_atomic_cmpxchgandroid_atomic_release_cas 它实际执行的函数是android_atomic_release_cas,这个函数的工作原理大概是这样的:如果它发现*addr == oldvalue,就会执行*addr = newvalue的操作,然后返回0,否则什么也不做,返回1。在我们讨论的这个场景中,oldvalue等于curCount,而newvalue等于curCount + 1,于是,在*addr == oldvalue的条件下,就相当于是对目标对象的强引用计数值增加了1。什么情况下*addr != oldvalue呢?在调用android_atomic_release_cas函数之前,oldvalue和值就是从地址addr读出来的,如果在执行android_atomic_release_cas函数的时候,有其它地方也对地址addr进行操作,那么就会有可能出现*addr != oldvalue的情况,这时候就说明其它地方也在操作目标对象的强引用计数了,因此,这里就不能执行增加目标对象的强引用计数的操作了,它必须要等到其它地方操作完目标对象的强引用计数之后再重新执行,这就是为什么要通过一个while循环来执行了。 第二种情况比较复杂一点,因为这时候目标对象可能还存在,也可能不存了,这要根据实际情况来判断。如果此时目标对象的强引用计数值等于INITIAL_STRONG_VALUE,说明此目标对象还从未被强指针引用过,这时候弱指针能够被提升为强指针的条件就为: allow=(impl->mFlags&OBJECT_LIFETIME_WEAK)!=OBJECT_LIFETIME_WEAK ||impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG,id); 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966569,如需转载请自行联系原作者

优秀的个人博客,低调大师

参加了iDOF2016会议,发表演讲“油田SOA与云平台的系统思考与实践”

PPT的全部抓图,扫描二维码直接到微信里去看吧: 本文转自申龙斌的程序人生博客园博文,原文链接:http://www.cnblogs.com/speeding/p/5988609.html,如需转载请自行联系原作者 ----==== Email: slofslb (GTD) qq.com 请将(GTD)换成@ ====---- 版权声明:自由转载-非商用-非衍生-保持署名( 创意共享3.0许可证) 作者: 申龙斌的程序人生 ---- 魔方、 桥牌、 象棋、游戏人生... ---- BASIC、C++、JAVA、 C#、 Haskell、 Objective-C、 Open Inventor、程序人生... ---- GTD伴我实现人生目标 ---- SeismicPro地震剖面显示程序 ---- Eclipse油藏数值模拟二进制文件格式解析和格式转换软件

优秀的个人博客,低调大师

《数据虚拟化:商务智能系统的数据架构与管理》一 1.8 数据虚拟化的不同实现

1.8 数据虚拟化的不同实现 技术上来说,许多不同的方式都可以实现数据虚拟化层。以下是一些例子:使用专用的数据虚拟化服务器,多个数据存储器看起来只是一个。应用程序只看见一个大的数据存储器,然而实际上数据存储在多个存储器中。一个企业服务总线(ESB)可以用来开发一个允许对数据标准访问的服务层。调用这些服务的数据使用者不需要知道数据在哪里、怎样被保存、它的存储结构、它的原始资源接口或者其他技术细节。他们只会看见,例如,一个SOAP接口或一个ReST(表述性状态转移)接口。在这种情况下,ESB是数据虚拟化层。想要了解更多关于ESB的信息,见文献[11]。把数据存储放到云中也是数据虚拟化的一种形式。访问一个数据存储时,数据使用者使用云API工作,它们并不知道数据本身存在哪里。数据的存储和管理是在本地还是远程是完全透明的。在某种程度上,使用从

优秀的个人博客,低调大师

《数据虚拟化:商务智能系统的数据架构与管理》一 1.5 数据虚拟化与相关概念

1.5 数据虚拟化与相关概念 数据虚拟化和IT产业中一些众所周知的其他概念密切相关,如封装、信息隐藏、抽象数据联合、数据集成和企业信息集成。本节解释这些概念和它们与数据虚拟化的关系。注意,关于这些概念存在不同的定义,并且有些人视这些概念为同义词。混淆这些概念的原因在文献[5]中Edward Berard已经表述得相当清晰:“抽象、信息隐藏和封装是非常不同但高度相关的概念。不难看出抽象、信息隐藏和封装是怎样相互混淆的。” 1.5.1 数据虚拟化与封装和信息隐藏 40多年前,David L. Parnas在1972年发表了开创性论文“On the Criteria to Be Used in Decomposing Systems into Modules”(见文献[6])。该论文已经出版了多次。在这个传奇的论文中,Parnas解释了对于应

优秀的个人博客,低调大师

《数据虚拟化:商务智能系统的数据架构与管理》一 1.11 数据集成的其他方式

1.11 数据集成的其他方式 使用数据虚拟化可以集成数据,但是这并不是集成来自不同数据存储中数据的唯一方式。正如1.4节所讲,存在不同的技术方法来集成数据,包括ETL、ELT和复制。本节会简要解释这些其他方式,更多信息参见2.7节。ETL(提取-转换-装载)是数据集成的一种方式,它在数据仓库环境中被大量使用。使用ETL,集成化可以通过从多个源数据存储中复制数据来实现,通过将集成的、转换的结果存储在独立的目标数据存储中来实现。保留集成化数据需要后者。目标数据存储可能是数据使用者正在访问的数据存储(如图1-10所示)。因为目标数据存储中的所有数据都是以某种方式从源数据存储中的数据导出的,所以它也被称为派生数据存储。 在复制过程中,数据被结合、转换和清洗。通常这个复制过程是预先安排好的。在确定的时间间隔内,新数据从数据源里被提取出来,集成并

优秀的个人博客,低调大师

《数据虚拟化:商务智能系统的数据架构与管理》一 2.3 管理层次与决策制定

2.3 管理层次与决策制定 决策制定这一主题与管理和在机构中建立的各级管理层次有直接关系。一个普遍表示管理层次的方法是通过管理金字塔(如图2-1所示)。 策略管理的重点在于整个机构的表现。大部分关于整个机构的决策由这一水平的管理制定。例如,我们是否要构建一个新机构?我们是否应该进军一个新的市场?机构是否应该扁平化管理?我们是否应该外包所有IT工作?策略管理层制定的策略长期影响今后的结果与目标。战术管理层关心的是一个机构的规划和控制单元,例如市场、销售和生产。通常他们制定的决策有短到中期的影响。操作管理层处理机构的日常操作。例如,第二天某一特定商店应该供应多少苏打水?机构有足够的司机可供调试去运送包裹吗?应该采取什么样的措施应对一架严重晚点的飞机,并且飞机上有许多不得不转机的旅客?

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册