作为boost库最重要的组成部分之一,智能指针是我们在应用boost时几乎无处不在的一个应用,这里简单研究一下windows下share_ptr的部分实现。
1.shared_ptr成员变量(shared_ptr.hpp)
template<class T> class shared_ptr
{
........
private:
T * px; // contained pointer
boost::detail::shared_count pn; // reference counter
}
成员变量px容易理解,是我们需要维护的对象指针,pn则是shared_ptr引用计数对象,决定什么时候删除px(当然是引用计数为0的时候)。
2.我们看看pn类型share_cout类成员(shared_count.hpp):
class shared_count
{
private:
sp_counted_base * pi_;
.................
}
share_count内部维护一个 sp_counted_base对象指针 pi,继续看sp_counted_base结构。
3.sp_counted_base结构(sp_counted_base_w32.hpp)
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
long weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
BOOST_INTERLOCKED_INCREMENT( &use_count_ );
}
bool add_ref_lock() // true on success
{
for( ;; )
{
long tmp = static_cast< long const volatile& >( use_count_ );
if( tmp == 0 ) return false;
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1200 )
// work around a code generation bug
long tmp2 = tmp + 1;
if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true;
#else
if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true;
#endif
}
}
void release() // nothrow
{
if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
BOOST_INTERLOCKED_INCREMENT( &weak_count_ );
}
void weak_release() // nothrow
{
if( BOOST_INTERLOCKED_DECREMENT( &weak_count_ ) == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<long const volatile &>( use_count_ );
}
};
哈哈,怎么样,到这一步,应该从这里大概就能看出一些端倪来了吧,总结一下。
3.1 两个long型的引用计数use_count和weak_count都出来了,这里控制share_ptr计数的应该是use_count,weak_count应该是维护weak_ptr计数的(例如你定义的类继承自enable_share_from_this就会发现weak_count的变话)。
3.2 从 virtual void dispose() = 0 和 virtual void * get_deleter( sp_typeinfo const & ti ) = 0 看出 sp_counted_base是个纯虚类,那么share_cout类应该维护的是sp_counted_base子类的指针,于是可以在share_count的代码中找到:
class shared_count
{
private:
sp_counted_base * pi_;
......
public:
........
template<class Y> explicit shared_count( Y * p ): pi_( 0 )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{
#ifndef BOOST_NO_EXCEPTIONS
try
{
pi_ = new sp_counted_impl_p<Y>( p );
}
catch(...)
{
boost::checked_delete( p );
throw;
}
这里可以找到实例化的子类是 sp_counted_impl_p。
3.2 可以看出来windows下share_ptr使用引用计数时的多线程同步机制了,看看BOOST_INTERLOCKED_DECREMENT、BOOST_INTERLOCKED_INCREMENT、BOOST_INTERLOCKED_COMPARE_EXCHANGE的宏定义吧
# define BOOST_INTERLOCKED_INCREMENT _InterlockedIncrement
# define BOOST_INTERLOCKED_DECREMENT _InterlockedDecrement
# define BOOST_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange
4.简单测试一下
class share_test
{
public:
share_test()
{
}
~share_test()
{
}
};
typedef boost::shared_ptr<share_test> share_test_ptr;
int _tmain(int argc, _TCHAR* argv[])
{
share_test_ptr p1(new share_test);
{
share_test_ptr p2 =p1;
p1.reset();
int i = 0;
}
return 0;
}
代码分析:
4.1 share_test_ptr p1(new share_test); 调用shared_ptr的构造函数,并初始化share_count的use_count和weak_count计数为1,
4.2 share_test_ptr p2=p1; 该语句内部先后调用:
pi_->add_ref_copy();使得use_count计数增1,此时use_count值为2step 1. shared_ptr( shared_ptr const & r ): px( r.px ), pn( r.pn ) // shared_ptr拷贝构造函数 { } step 2. shared_count(shared_count const & r): pi_(r.pi_) // shared_count拷贝构造函数 { if( pi_ != 0 ) pi_->add_ref_copy(); }
4.3 p1.reset();该语句内部先后调用:在reset函数中this_type().swap(*this)相当于shared_ptr<share_test>().swap(p1),reset函数构造了一个shared_pt<share_test>局部变量(调用的是无参构造函数,其中px=null,pn.pi_=null),交换后局部对象析构,导致引用计数减1.step 1. void reset() // shared_ptr.reset { this_type().swap(*this); //typedef shared_ptr<T> this_type; } step 2. boost::shared_ptr<share_test>::~shared_ptr<share_test>() //析构函数 step 3. ~shared_count() // shared_count析构函数 { if( pi_ != 0 ) pi_->release(); #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) id_ = 0; #endif }