浅析boost之智能指针—shared_ptr

 作为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; 该语句内部先后调用:
step 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();
    }
pi_->add_ref_copy();使得use_count计数增1,此时use_count值为2
4.3 p1.reset();该语句内部先后调用:
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
    }

在reset函数中this_type().swap(*this)相当于shared_ptr<share_test>().swap(p1),reset函数构造了一个shared_pt<share_test>局部变量(调用的是无参构造函数,其中px=null,pn.pi_=null),交换后局部对象析构,导致引用计数减1.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值