shared_ptr是平时用的比较多的智能指针类型,本人基本了解智能指针的原理是通过引用计数来实现的,之前也实现过一个,后来shared_ptr出现后就不再使用其它的了,boost文档中提到shared_ptr是线程安全的,对线程安全比较好奇,所以察看了shared_ptr的源代码。
shared_ptr的源代码略复杂,各种构造函数占用了较大的篇幅,之后是reset,*和-〉的运算符重载等。总的来说思路是常规思路。
shared_ptr有两个成员
-
T * px; // 指针
-
boost::detail::shared_count pn; // 引用计数 -- 后面介绍
看一下swap函数。这个函数在shared_ptr内部使用的较多
-
void swap(shared_ptr<T> & other) // never throws
-
{
-
std::swap(px, other.px);
-
pn.swap(other.pn);
-
}
该函数调用std的swap函数交换 指针,然后调用shared_count::swap替换引用计数。
线程安全分为几个场景:比如多个thread同时读、同时写、同是读写。从这一点看shared_ptr同时读没有问题的,但是同时写或同时读写就会有问题了,所以shared_ptr并不是完全线程安全的。
shared_ptr的核心就是shared_count,因为整个shared_ptr实现都没有出现对引用计数的具体操作,比如+1 -1等。而每一次需要用到对引用计数的操作都调用了shared_count内部封装的函数,比如:swap、==、get_deleter、use_count等。
shared_count 内部包含sp_counted_base *pi_,该成员在shared_count的构造函数里初始化,从名字可以看出sp_counted_base是一个基类。shared_count在构造函数里对*pi_进行初始化。
点击(此处)折叠或打开
-
template<class Y> explicit shared_count( Y * p ): pi_( 0 )
-
{
-
……
-
pi_ = new sp_counted_impl_p<Y>( p );
-
……
-
}
-
-
template<class P, class D> shared_count( P p, D d ): pi_(0)
-
{
-
……
-
pi_ = new sp_counted_impl_pd<P, D>(p, d);
-
……
-
}
sp_counted_base 类主要对引用计数进行管理,它内部包含两个成员:
-
long use_count_; // #shared
-
long weak_count_; // #weak + (#shared != 0)
这两个成员是私有的,只能通过成员函数进行修改,比如:
-
void add_ref_copy()
-
{
-
++use_count_;
-
}
其他的成员函数还有:add_ref_lock() 、 release()等都是对引用计数操作。
-
void release() // nothrow
-
{
-
if( --use_count_ == 0 )
-
{
-
dispose();
-
weak_release();
-
}
-
}
release函数调用了dispose,该函数是纯虚函数,该函数在其他 sp_counted_base 的子类里面实现,weak_release暂时不讨论。
-
virtual void dispose() = 0; // nothrow
我们看一下 sp_counted_impl_pd 的实现,sp_counted_impl_pd 是 sp_counted_base的子类,有两个成员
-
P ptr; // copy constructor must not throw
-
D del; // copy constructor must not throw
sp_counted_impl_pd内部对new 和 delete进行了重载,并且实现了dispose():
-
virtual void dispose() // nothrow
-
{
-
del( ptr );
-
}
del应该是一个函数对象,当use_count_为0时调用该函数对象,官方的解释是定制销毁器,就是如果我们的对象不是通过new分配的,所以不能通过delete销毁,那就需要用户指定销毁方式。
阅读(3143) | 评论(0) | 转发(0) |