如何实现一个引用计数?

来源:互联网 发布:工业和制造业数据 编辑:程序博客网 时间:2024/04/28 17:28
  • 要保证线程安全、要保证高效。
  • 这是一个跟芯片架构、编译器都相关的工作。
  • 剖析boost::detail::shared_ptr的计数实现机制:
// shared_ptr中的引用计数成员属性pnboost::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.0shared_ptrshared_count sp_counted_base各平台实现结束

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

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

0 0
原创粉丝点击