gcc从4.1.2版本开始提供了__sync_*系列的内置API,用于加减和逻辑运算,可以对1,2,4,8字节长度的数值或指针类型进行原子操作。为方便使用,个人对这些API作了简单的封装,主模板类如下: 1
template<typename T>
2
class atomic_base
3
{
4
public:
5
typedef T int_type;
6
typedef atomic_base<T> self_type;
7
8
public:
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
92
private:
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为指针类型时,指针的加减和逻辑运算没有意义,但对于指针加减一个数值是有意义的,因此前两者操作保留但需要重定义,但没有后三者操作,需要特化实现,其模板类如下:
1
template<typename T>
2
class atomic_base<T*>
3
{
4
public:
5
typedef T* pointer_type;
6
typedef atomic_base<T*> self_type;
7
8
public:
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
74
private:
75
T* val_;
76
}; 同理,上面析构函数中,使用了BOOST_STATIC_ASSERT宏来作编译期约束,确保类型T的指针大小为1,2,4,8字节长度。在这里,要注意一个特例,大小为1字节的类型包括bool布尔类型,它的取值只有true或false两种可能,不存在加减运算操作,也没有意义,但逻辑运算是有意义的,因此需要特化实现,其模板类如下:
1
template<>
2
class atomic_base<bool>
3
{
4
public:
5
typedef atomic_base<bool> self_type;
6
public:
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
47
private:
48
bool val_;
49
}; 针对常见的基本数值类型,定义了其类型别名,如下:
1
typedef atomic_base<bool> atomic_bool;
2
typedef atomic_base<signed char> atomic_char;
3
typedef atomic_base<unsigned char> atomic_uchar;
4
typedef atomic_base<short> atomic_short;
5
typedef atomic_base<unsigned short> atomic_ushort;
6
typedef atomic_base<int> atomic_int;
7
typedef atomic_base<unsigned int> atomic_uint;
8
typedef atomic_base<long> atomic_long;
9
typedef atomic_base<unsigned long> atomic_ulong;
10
typedef atomic_base<long long> atomic_llong;
11
typedef 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
老马驿站 阅读(979)
评论(0) 编辑 收藏 引用 所属分类:
linux