-
Notifications
You must be signed in to change notification settings - Fork 0
/
atomic.h
142 lines (113 loc) · 4.45 KB
/
atomic.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#ifndef ATOMIC_H_
#define ATOMIC_H_
#include <stdint.h>
#include <type_traits>
#include "atomic_ops.h"
template <typename T, bool IsIntegral>
class atomic_impl {};
struct IS_POD_TYPE {};
template <typename T>
class atomic_impl<T, true> : public IS_POD_TYPE {
public:
// The current value of the atomic number
volatile T value;
// Creates an atomic number with value "value"
atomic_impl(const T& value = T()) : value(value) {}
// Performs an atomic increment / decrement by 1, returning the new value
T inc() { return __sync_add_and_fetch(&value, 1); }
T dec() { return __sync_sub_and_fetch(&value, 1); }
// Lvalue implicit cast
operator T() const { return value; }
// Performs an atomic increment / decrement by 1, returning the new value
T operator++() { return inc(); }
T operator--() { return dec(); }
// Performs an atomic increment / decrement by "val", returning the new value
T inc(const T val) { return __sync_add_and_fetch(&value, val); }
T dec(const T val) { return __sync_sub_and_fetch(&value, val); }
// Performs an atomic increment / decrement by "val", returning the new value
T operator+=(const T val) { return inc(val); }
T operator-=(const T val) { return dec(val); }
// Performs an atomic increment / decrement by 1, returning the old value
T inc_ret_last() { return __sync_fetch_and_add(&value, 1); }
T dec_ret_last() { return __sync_fetch_add_sub(&value, 1); }
// Performs an atomic increment / decrement by 1, returning thd old value
T operator++(int) { return inc_ret_last(); }
T operator--(int) { return dec_ret_last(); }
// Performs an atomic increment / decrement by "val", returning the old value
T inc_ret_last(const T val) { return __sync_fetch_and_add(&value, val); }
T dec_ret_last(const T val) { return __sync_fetch_and_sub(&value, val); }
// Performs an atomic exchange with "val", returning the previous value
T exchange(const T val) { return __sync_lock_test_and_set(&value, val); }
};
template <typename T>
class atomic_impl<T, false> : public IS_POD_TYPE {
public:
// The current value of the atomic number
volatile T value;
// Creates an atomic number with value "value"
atomic_impl(const T& value = T()) : value(value) {}
// Performs an atomic increment / decrement by 1, returning the new value
T inc() { return inc(1); }
T dec() { return dec(1); }
// Lvalue implicit cast
operator T() const { return value; }
// Performs an atomic increment / decrement by 1, returning the new value
T operator++() { return inc(); }
T operator--() { return dec(); }
// Performs an atomic increment / decrement by "val", returning the new value
T inc(const T val) {
T prev_value;
T new_value;
do {
prev_value = value;
new_value = prev_value + val;
} while (!atomic_compare_and_swap(value, prev_value, new_value));
return new_value;
}
T dec(const T val) {
T prev_value;
T new_value;
do {
prev_value = value;
new_value = prev_value - val;
} while (!atomic_compare_and_swap(value, prev_value, new_value));
return new_value;
}
// Performs an atomic increment / decrement by "val", returning the new value
T operator+=(const T val) { return inc(val); }
T operator-=(const T val) { return dec(val); }
// Performs an atomic increment / decrement by 1, returning the old value
T inc_ret_last() { return inc_ret_last(1); }
T dec_ret_last() { return dec_ret_last(1); }
// Performs an atomic increment / decrement by 1, returning thd old value
T operator++(int) { return inc_ret_last(); }
T operator--(int) { return dec_ret_last(); }
// Performs an atomic increment / decrement by "val", returning the old value
T inc_ret_last(const T val) {
T prev_value;
T new_value;
do {
prev_value = value;
new_value = prev_value + val;
} while (!atomic_compare_and_swap(value, prev_value, new_value));
return prev_value;
}
T dec_ret_last(const T val) {
T prev_value;
T new_value;
do {
prev_value = value;
new_value = prev_value - val;
} while (!atomic_compare_and_swap(value, prev_value, new_value));
return prev_value;
}
// Performs an atomic exchange with "val", returning the previous value
T exchange(const T val) { return __sync_lock_test_and_set(&value, val); }
};
template <typename T>
class atomic : public atomic_impl<T, std::is_integral<T>::value> {
public:
atomic(const T& value = T())
: atomic_impl<T, std::is_integral<T>::value>(value) {}
};
#endif