随笔-167  评论-8  文章-0  trackbacks-0
   gcc从4.1.2版本开始提供了__sync_*系列的内置API,用于加减和逻辑运算,可以对1,2,4,8字节长度的数值或指针类型进行原子操作。为方便使用,个人对这些API作了简单的封装,主模板类如下:   
 1template<typename T>
 2class atomic_base 
 3{
 4public:
 5    typedef T int_type;
 6    typedef atomic_base<T> self_type;
 7
 8public:
 9    atomic_base(int_type val = int_type())
10    : val_(val)
11    {
12    }

13
14    ~atomic_base()
15    {
16        BOOST_STATIC_ASSERT(sizeof(int_type)==1||sizeof(int_type)==2||sizeof(int_type)==4||sizeof(int_type)==8);
17    }

18
19    atomic_base(const self_type& other)
20    {
21        int_type val = other;
22        __sync_lock_test_and_set(&val_, val);
23    }

24
25    self_type& operator = (const self_type& other)
26    {
27        if (this!=&other)
28        {
29            int_type val = other;
30            __sync_lock_test_and_set(&val_, val);
31        }

32        return *this;
33    }

34    
35    operator int_type() const
36    {
37        return __sync_val_compare_and_swap(const_cast<volatile int_type*>(&val_),0,0);
38    }

39    
40    self_type operator++(int)
41    {
42        return __sync_fetch_and_add(&val_,1);
43    }

44
45    self_type& operator++()
46    {
47        __sync_add_and_fetch(&val_,1);
48        return *this;
49    }

50
51    self_type operator--(int)
52    {
53        return __sync_fetch_and_sub(&val_,1);
54    }

55
56    self_type& operator--()
57    {
58        __sync_sub_and_fetch(&val_,1);
59        return *this;
60    }

61
62    self_type& operator+=(int_type val)
63    {
64        __sync_add_and_fetch(&val_,val);
65        return *this;
66    }

67
68    self_type& operator-=(int_type val)
69    {
70        __sync_sub_and_fetch(&val_,val);
71        return *this;
72    }

73
74    self_type& operator&=(int_type val)
75    
76        __sync_and_and_fetch(&val_, val); 
77        return *this;
78    }

79
80    self_type& operator|=(int_type val)
81    {
82        __sync_or_and_fetch(&val_,val); 
83        return *this;
84    }

85    
86    self_type& operator^=(int_type val)
87    {
88        __sync_xor_and_fetch(&val_,val); 
89        return *this;
90    }

91
92private:
93    T val_;
94}
;
   上面析构函数中,使用了BOOST_STATIC_ASSERT宏来作编译期约束,确保类型T大小为1,2,4,8字节长度。由于提供了T到atomic_base的隐式转换和转型操作,因此没有必要再定义operato +,operator - ,opeator ^,operator |,operator &运算符成员或友元重载操作。由于主模板定义了operator+=,operator-=,operator&=,operator|=,operator^=运算符重载操作,但当T为指针类型时,指针的加减和逻辑运算没有意义,但对于指针加减一个数值是有意义的,因此前两者操作保留但需要重定义,但没有后三者操作,需要特化实现,其模板类如下:
 1template<typename T>
 2class atomic_base<T*> 
 3{
 4public:
 5    typedef T* pointer_type;
 6    typedef atomic_base<T*> self_type;
 7
 8public:
 9    atomic_base(pointer_type val = NULL)
10        : val_(val)
11    {
12    }

13
14    atomic_base(const self_type& other)
15    {
16        pointer_type val = other;
17        __sync_lock_test_and_set(&val_, val);
18    }

19
20    ~atomic_base()
21    {
22        BOOST_STATIC_ASSERT(sizeof(pointer_type)==1||sizeof(pointer_type)==2||sizeof(pointer_type)==4||sizeof(pointer_type)==8);
23    }

24
25    self_type& operator=(const self_type& other)
26    {
27        if (this!=&other)
28        {
29            pointer_type val = other;
30            __sync_lock_test_and_set(&val_, val);
31        }

32        return *this;
33    }

34
35    operator pointer_type() const
36    {
37        return __sync_val_compare_and_swap(const_cast<volatile pointer_type*>(&val_),0,0);
38    }

39
40    self_type operator++(int)
41    {
42        return __sync_fetch_and_add(&val_,1);
43    }

44
45    self_type& operator++()
46    {
47        __sync_add_and_fetch(&val_,1);
48        return *this;
49    }

50
51    self_type operator--(int)
52    {
53        return __sync_fetch_and_sub(&val_,1);
54    }

55
56    self_type& operator--()
57    {
58        __sync_sub_and_fetch(&val_,1);
59        return *this;
60    }

61
62    self_type& operator+=(std::ptrdiff_t d)
63    {
64        __sync_add_and_fetch(&val_,d);
65        return *this;
66    }

67
68    self_type& operator-=(std::ptrdiff_t d)
69    {
70        __sync_sub_and_fetch(&val_,d);
71        return *this;
72    }

73
74private:
75    T* val_;
76}
;
  同理,上面析构函数中,使用了BOOST_STATIC_ASSERT宏来作编译期约束,确保类型T的指针大小为1,2,4,8字节长度。在这里,要注意一个特例,大小为1字节的类型包括bool布尔类型,它的取值只有true或false两种可能,不存在加减运算操作,也没有意义,但逻辑运算是有意义的,因此需要特化实现,其模板类如下:
 1template<>
 2class atomic_base<bool>
 3{
 4public:
 5    typedef atomic_base<bool> self_type;
 6public:
 7    atomic_base(bool val = false)
 8        : val_(val)
 9    {
10    }

11    
12    atomic_base(const self_type& other)
13    {
14        __sync_lock_test_and_set(&val_, other.val_);
15    }

16    
17    self_type& operator=(const self_type& other)
18    {
19        if (this!=&other)
20            __sync_lock_test_and_set(&val_, other.val_);
21        return *this;
22    }

23    
24    operator bool() const
25    {
26        return __sync_val_compare_and_swap(const_cast<volatile bool*>(&val_),0,0);
27    }

28
29    self_type& operator&=(bool val)
30    
31        __sync_and_and_fetch(&val_, val); 
32        return *this;
33    }

34
35    self_type& operator|=(bool val)
36    {
37        __sync_or_and_fetch(&val_,val); 
38        return *this;
39    }

40
41    self_type& operator^=(bool val)
42    {
43        __sync_xor_and_fetch(&val_,val); 
44        return *this;
45    }

46
47private:
48    bool val_;
49}
;
   针对常见的基本数值类型,定义了其类型别名,如下:
 1typedef atomic_base<bool>                     atomic_bool;
 2typedef atomic_base<signed char>           atomic_char;
 3typedef atomic_base<unsigned char>        atomic_uchar;
 4typedef atomic_base<short>                    atomic_short;
 5typedef atomic_base<unsigned short>       atomic_ushort;
 6typedef atomic_base<int>                       atomic_int;
 7typedef atomic_base<unsigned int>          atomic_uint;
 8typedef atomic_base<long>                     atomic_long;
 9typedef atomic_base<unsigned long>        atomic_ulong;
10typedef atomic_base<long long>              atomic_llong;
11typedef atomic_base<unsigned long long>  atomic_ullong;
   幸运的是,从gcc 4.4起,标准库就提供了atomic C++类,尤其是4.6(支持C++0x标准),作了很好的封装,相关头文件是atomic_base.h, atomic_0.h, atomic_2.h, atomic.h。
posted on 2011-09-13 18:58 老马驿站 阅读(976) 评论(0)  编辑 收藏 引用 所属分类: linux