com关于引用计数

实现引用计数并不难,但在什么层次上进行引用计数呢?


依照com规范,一个com组件能够实现多个com对象。而且每一个com对象又能够支持多个com接口,这样的层次结构为我们实现引用计数提供了多种选择方案。

我们能够选择在com组件一级实现引用计数,也能够选择在com对象一级实现引用计数。甚至能够为对象的每一个接口设置一个引用计数。

三张选择方案都有各自的优缺点。


1)设置一个针对整个组件全局的引用计数。

在实现组件时,我们用一个全局整数变量记录引用计数值,当组件被初始装入内存时,该计数值为0。当有对象被创建时,计数值開始添加,在整个组件被使用的过程中,计数值一直保持大于0,当组件中的全部对象都被用完之后。计数值应该减回到0,于是组件模块九能够从内存中卸出。

这样的引用计数能够控制组件模块的生存周期,但不能控制com对象的生存周期。试想,假设这个组件程序在执行过程中产生了两个com对象,无论是同一类的对象还是不同类的对象,当某一个对象被减1时,由于减1是对全局引用计数进行的。所以它无法从引用计数上推断是否该对象已经不再被使用了。必须等到全部的对象都被使用完了之后,即全局引用计数减到0时。全部的对象才干够一起被释放。

这样做自然减少了系统资源的利用率。这个缺点我们能够称之为“计数分辨率太粗”。由于计数值包括了全部组件全部接口的使用记录,它只控制组件模块的生存期。


2)为每一个com对象设置一个引用计数。在实现com对象时,用一个与组件对象具有相同生存期的整数变量记录引用计数值,当对象被创建时。计数值開始从0添加;仅仅要对象还在被客户程序使用,则计数值大于0。当客户不再使用该对象时,计数值应该减回到0,于是对象所占用的资源被释放掉以便为系统又一次使用。

在对象一级设置引用计数能够避免”计数分辨率太粗“的缺点,对于多个对象的组件程序能够有效地提高系统资源利用率。但每当一个对象被释放掉之后,它必须通知组件程序。假设组件程序发现已经没有对象存在了。则组件模块应该能够从内存中卸出。因此,组件程序应该保持一份有效对象的记录,能够用一个全局的对象计数值来控制组件生存周期。

当对象被释放时,同一时候组件的对象计数值也减1,假设对象计数值为0,则表明组件模块能够从内存中卸出。


3)为每一个接口设置一个引用计数。由于客户通过接口指针与组件对象进行通信。所以为每一个接口设置引用计数能够跟踪客户对com对象的使用情况。客户并不一定用到对象全部的接口,对于实现多个接口的对象,非常有可能某些接口没有被客户使用到,那么只与这些接口相关的资源就能够不被占用。

在接口一级设置引用计数使得“计数分辨率”非常细,通过接口的引用计数能够有效地掌握客户对接口的使用情况,这对于我们调试组件程序和分析客户程序的使用情况非常有帮助。但每当一个接口的引用计数减回到0时,它必须给对象发出通知,对象在接到通知后,须要怕安段是否全部的接口计数都为0,假设是,对象就必须把自己给释放掉。完毕清除工作。再进一步通知组件程序,组件程序接到通知后推断是否全部的对象都已经被清除。假设是。则它能够被卸出内存。

由于这样的通知时必须的,所以在接口一级实现引用计数有“计数分辨率太细”之嫌。


假设在组件一级实现引用计数。自然能够选择全局变量;假设在对象一级实现引用计数,我们能够使用C++类的成员变量;假设在接口一级实现引用计数。我们能够为对象实现的每个接口设置一个类成员变量作为引用计数变量。

通过上面的分析,从这样的的角度出发,比較合理的方案是採用对象一级的引用计数以便控制对象和组件的生存周期。

原文地址:https://www.cnblogs.com/jzssuanfa/p/7157565.html