WebKit的智能指针分析 - Part 1:RefCounted
来源:互联网 发布:泰国 知乎 编辑:程序博客网 时间:2024/05/16 04:42
在WebKit的官网上有一篇使用指南:RefPtr and PassRefPtr Basics,从应用的角度讲解了RefPtr类族的由来,及使用方法。但很无厘头的是,这里面居然没有提到如何创建一个有引用计数功能的类!?(教你如何用砖头造房子却不教你如何造砖头)
在抱怨作者的粗心、懒惰、和恶搞精神后,我只能用一句俗话来安慰自己:还好有源代码,还好有源代码,⋯⋯WebKit我来了!!!
WebKit是个非常优秀的开源项目,应用范围广就不说了(safari、chrome、iphone、android、⋯⋯),代码质量也是高得一塌糊涂:清晰的模块划分、清晰的代码组织架构、晦涩(巧妙的同义词)的C++小技巧等优点完全值得有心提高内功的同志一读。
下面就是我在学习WebKit源代码里的RefPtr智能指针的一些心得。
Overview
WebKit的智能指针由类族 RefPtr 来实现,其核心由三个类组成:
- RefCounted
- RefPtr
- PassRefPtr
其中RefCounted提供了引用计数器(一个int型成员),而RefPtr和PassRefPtr则提供了自动管理引用计数器的功能。根据RefPtr and PassRefPtr Basics的说法,最初并没有RefPtr和PassRefPtr,这两个类是2005年才加入的,在它们出现之前完全是靠找死的人工管理RefCounted的引用计数。RefCounted类本身是没有问题的,但它的使用方法相当繁琐,繁琐到开发人员发现很多内存泄露都是由于对方法ref()和deref()的调用不当而造成一半以上内存泄露的程度。为了简化RefCounted的使用方法,RefPtr诞生了,而为了更高效地传递参数,开发人员又创造了PassRefPtr。
RefCounted
RefCounted的源代码在这里:RefCounted.h。
这个文件里定义了两个类:非模板类RefCountedBase和模板类RefCounted,从名字上就能看出来RefCounted继承于RefCountedBase。像维护引用计数器这么简单的活儿只使用一个类就绰绰有余了,这里之所以做成两个类是为了减少template hoisting(实例化模板导致的代码膨胀)。总而言之,最终的RefCounted完成了这样的功能:
- 定义了成员变量:int m_refCount
- 定义函数ref12345
//
void
ref()
{
++m_refCount;
}
- 定义函数derefderefBase的定义是:123456
//
void
deref()
{
if
(derefBase())
delete
static_cast
<T*>(
this
);
}
1234567891011//
// Returns whether the pointer should be freed or not.
bool
derefBase()
{
if
(m_refCount == 1) {
return
true
;
}
--m_refCount;
return
false
;
}
上面的ref()和deref()就是RefCounted的核心功能了,不过有一点要注意的是RefCounted的析构函数是protected的,这样就不能直接定义RefCounted对象了,而是必须从RefCounted继承子类才能行。但是这里不同于一般的继承,这里玩了个小trick:
class
Frame :
public
RefCounted<Frame> {
// ...
}
和一般的继承不一样吧,之所以要写成这样的原因在于函数deref()能够删除正确的对象!在函数deref()里,如果计数器到了1,就必须把自己销毁(即delete this),但此时的RefCounted直接来一句delete this是不对的,因为如果有一个类Foo继承于RefCounted,那在RefCounted的成员函数里调用delete this只会触发RefCounted的析构函数,而不会触发Foo的析构函数。为了让RefCounted在delete this时能确定子类的类型,类Foo就得从RefCounted<Foo>继承,这样才能为在RefCounted中delete this提供便利:
delete
static_cast
<T*>(
this
);
在编译时T的类型会被确定为Foo,因此上面这句代码会触发Foo的析构函数,另外由于Foo继承于RefCounted,RefCounted的析构函数随后会调用(虽然啥也没干)。
- WebKit的智能指针分析 - Part 1:RefCounted
- WebKit的智能指针分析 - Part 1:RefCounted
- WebKit的智能指针分析 - Part 1:RefCounted
- WebKit的智能指针分析 - Part 1:RefCounted
- WebKit的智能指针分析 - Part 1:RefCounted
- webkit 智能指针分析
- 探索WebKit内核(五)------ 智能指针解析:RefCounted, RefPtr, PassRefPtr, OwnPtr和PassOwnPtr
- WebKit源代码里的RefCounted
- Chromium和WebKit的智能指针实现原理分析
- WebKit源代码里的RefPtr智能指针
- webkit内存管理1:智能指针
- WebKit中的智能指针
- WebKit中的智能指针
- WebKit中智能指针
- webkit中智能指针
- WebKit之智能指针
- webkit智能指针 - RefPtr, PassRefPtr
- Android之chromimu和webkit的智能指针的原理
- 智能指针
- 读CopyOnWriteArrayList有感
- ACE的ACE_Logging_Strategy类中的一个多线程安全问题的发现及解决过程
- ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第六篇:拦截器
- S3C2440中断解析和基于WINCE操作系统的中断分析(整理于网络,用于按键中断使用)
- WebKit的智能指针分析 - Part 1:RefCounted
- ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第七篇:闲话ASP.NET MVC
- android 系统定制的小技巧(网络收集)
- 一日一点RakNet(44)--NAT Type detection
- iPHone限定设备。
- shell-init: error retrieving current directory
- Write buffer的作用
- cluster_interconnec
- android 修改谷歌拼音输入法全屏时的高度