如何实现一个引用计数?

  • 要保证线程安全、要保证高效。
  • 这是一个跟芯片架构、编译器都相关的工作。
  • 剖析boost::detail::shared_ptr的计数实现机制:
// shared_ptr中的引用计数成员属性pn
boost::detail::shared_count pn;    // reference counter

// shared_count中的pi成员属性
sp_counted_base * pi_;

// sp_counted_base中的use_count_成员属性(取w32实现为例)
long use_count_;        // #shared

// 增减引用计数的w32平台具体实现
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_SP_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true;

#else

            if( BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true;

#endif
        }
    }

    void release() // nothrow
    {
        if( BOOST_SP_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
        {
            dispose();
            weak_release();
        }
    }

// 也有直接用汇编实现线程安全的自增自减,例如gcc编译器相关的mips架构下的实现

inline void atomic_increment( int * pw )
{
    // ++*pw;

    int tmp;

    __asm__ __volatile__
    (
        "0:\n\t"
        ".set push\n\t"
        ".set mips2\n\t"
        "ll %0, %1\n\t"
        "addiu %0, 1\n\t"
        "sc %0, %1\n\t"
        ".set pop\n\t"
        "beqz %0, 0b":
        "=&r"( tmp ), "=m"( *pw ):
        "m"( *pw )
    );
}

inline int atomic_decrement( int * pw )
{
    // return --*pw;

    int rv, tmp;

    __asm__ __volatile__
    (
        "0:\n\t"
        ".set push\n\t"
        ".set mips2\n\t"
        "ll %1, %2\n\t"
        "addiu %0, %1, -1\n\t"
        "sc %0, %2\n\t"
        ".set pop\n\t"
        "beqz %0, 0b\n\t"
        "addiu %0, %1, -1":
        "=&r"( rv ), "=&r"( tmp ), "=m"( *pw ):
        "m"( *pw ):
        "memory"
    );

    return rv;
}
Created with Raphaël 2.1.0 shared_ptr shared_count sp_counted_base 各平台实现 结束

实际上,实现一个跨平台的引用计数相当困难,但是boost做到了。
各编译器-芯片架构平台列表如下,
这里写图片描述
sp_counted_base_后面的部分即是编译器-芯片架构。例如sp_counted_base_acc_ia64,是acc编译器的ia64的CPU芯片架构。

为什么会与编译器和芯片架构都有关系?因为代码最终转为二进制代码时是通过编译器转的,而编译器如果对应不同芯片架构,没有实现统一的api接口,就需要与芯片架构相关。
而w32和clang都没有后缀对应的芯片架构,是指它们都实现了各种架构下的统一底层api。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值