平台无关的高效原子操作:ACE_Atomic_Op

         在软件开发中,我们经常会遇到多个线程对同一数据操作的同步问题,如果需要同步保护的是一组变量,则直接分用互斥锁进行保护,可以如果需要保护的只是一个整数(如:int,long...),则有更为高效的办法:ACE_Atomic_Op


ACE_Atomic_Op<class ACE_LOCK, class TYPE>是ACE提高的一个对不同平台上对象原子操作的一个包装类。这个类能过重写各种操作符(+=,++,--,=...)的实现,提供了对对象(由TYPE参数确定)的所有常见操作(+=,++,--,=...)的多线程保护!

由于我当前的需求,我要重点关注的是这个模板类的两个特化实现!
ACE_Atomic_Op<ACE_Thread_Mutex, long>
ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>


这两个特化实现,针对整数的操作进行了特别的优化,它根据所在的 平台 及 CPU 的个数来选择最高效的方法,使对单个整数的读写保护不需要使用互斥锁就可完成, 效率有了极大的提高。

让我们来看一下它的源代码:

1. 初始化
      在ACE::init调用时,会能过调用ACE_Atomic_Op::init_functions函数,初始化相关的原子操作函数:
       void
       ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::init_functions (void)
       {
        if (ACE_OS::num_processors () == 1)
           { //当前系统只有单个CPU
             increment_fn_ = single_cpu_increment;
             decrement_fn_ = single_cpu_decrement;
             exchange_fn_ = single_cpu_exchange;
             exchange_add_fn_ = single_cpu_exchange_add;
           }
       else
           {//当前系统有多个CPU
             increment_fn_ = multi_cpu_increment;
             decrement_fn_ = multi_cpu_decrement;
           exchange_fn_ = multi_cpu_exchange;
             exchange_add_fn_ = multi_cpu_exchange_add;
          }
       }


   2. 具体操作:
      ACE_Atomic_Op支持对整数的加减等常见操作,以我们++操作为例:
       ACE_INLINE unsigned long
       ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::operator++ (void)
       {
       #if defined (WIN32)
        return static_cast<unsigned long> (::InterlockedIncrement (const_cast<long *>                      (reinterpret_cast<volatile long *>(&this->value_))));
       #else /* WIN32 */
       return static_cast<unsigned long> ((*increment_fn_) (reinterpret_cast<volatile long *> (&this->value_)));
       #endif /* WIN32 */
       }

      
        当在Win32平台时会调用windows提供的原子加操作API,再在其平台上,会调用在初始化时所指确定的原子加操作函数,这些函数其基上都是使用各平台提供相关汇编指令实现的。所有这些操作不用加锁就可完成原子操作,效率非常高!
        以下为单CPU上加的原子操作函数实现代码:
       long
       single_cpu_exchange_add (volatile long *value, long rhs)
       {
       #if defined (ACE_HAS_INTEL_ASSEMBLY)
       unsigned long addr = reinterpret_cast<unsigned long> (value);
       asm( "xadd %0, (%1)" : "+r"(rhs) : "r"(addr) );
        return rhs;
       #elif defined (sun) || \
          (defined (__SUNPRO_CC) && (defined (__i386) || defined (__x86_64)))
       return ace_atomic_swap_add_long (
                  reinterpret_cast<volatile unsigned long*> (value), rhs);
       #elif defined(__GNUC__) && defined(PPC)
        long tmp;
       asm("add %0,%1,%2" : "=r" (tmp) : "r" (*value), "r" (rhs) );
        asm("stw %0,%1" : "+r" (tmp), "=m" (*value) );
        return tmp;
       #elif defined (WIN32) && !defined (ACE_HAS_INTERLOCKED_EXCHANGEADD)
       # if defined (_MSC_VER)
        __asm
         {
             mov eax, rhs
           mov edx, value
             xadd [edx], eax
          }
       // Return value is already in EAX register.
       # elif defined (__BORLANDC__)
        _EAX = rhs;
       _EDX = reinterpret_cast<unsigned long> (value);
       __emit__(0x0F, 0xC1, 0x02); // xadd [edx], eax
       // Return value is already in EAX register.
       # else /* _MSC_VER */
       ACE_UNUSED_ARG (value);
        ACE_UNUSED_ARG (rhs);
       ACE_NOTSUP_RETURN (-1);
       # endif /* _MSC_VER */
       #else /* ACE_HAS_INTEL_ASSEMBLY*/
       ACE_UNUSED_ARG (value);
       ACE_UNUSED_ARG (rhs);
        ACE_NOTSUP_RETURN (-1);
       #endif /* ACE_HAS_INTEL_ASSEMBLY*/
       }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值