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
老马驿站 阅读(974)
评论(0) 编辑 收藏 引用 所属分类:
linux