@@ -19,9 +19,11 @@ namespace icinga
19
19
* initialization by std::atomic_init, see LWG issue 2334."
20
20
* -- https://en.cppreference.com/w/cpp/atomic/atomic/atomic
21
21
*
22
+ * Also, the second template parameter allows to specify the default memory order once for all operations.
23
+ *
22
24
* @ingroup base
23
25
*/
24
- template <class T >
26
+ template <class T , std::memory_order m = std::memory_order_seq_cst >
25
27
class Atomic : public std ::atomic<T> {
26
28
public:
27
29
/* *
@@ -32,6 +34,118 @@ class Atomic : public std::atomic<T> {
32
34
inline Atomic (T desired) : std::atomic<T>(desired)
33
35
{
34
36
}
37
+
38
+ // The following methods have an argument with a default of std::memory_order_seq_cst hardcoded in the base class.
39
+ // Hence, we need to override them here to allow for a different default memory order.
40
+
41
+ void store (T desired, std::memory_order mo = m) noexcept
42
+ {
43
+ std::atomic<T>::store (desired, mo);
44
+ }
45
+
46
+ T load (std::memory_order mo = m) const noexcept
47
+ {
48
+ return std::atomic<T>::load (mo);
49
+ }
50
+
51
+ T exchange (T desired, std::memory_order mo = m) noexcept
52
+ {
53
+ return std::atomic<T>::exchange (desired, mo);
54
+ }
55
+
56
+ bool compare_exchange_weak (T& expected, T desired, std::memory_order mo = m) noexcept
57
+ {
58
+ return std::atomic<T>::compare_exchange_weak (expected, desired, mo);
59
+ }
60
+
61
+ bool compare_exchange_strong (T& expected, T desired, std::memory_order mo = m) noexcept
62
+ {
63
+ return std::atomic<T>::compare_exchange_strong (expected, desired, mo);
64
+ }
65
+
66
+ T fetch_add (T delta, std::memory_order mo = m) noexcept
67
+ {
68
+ return std::atomic<T>::fetch_add (delta, mo);
69
+ }
70
+
71
+ T fetch_sub (T delta, std::memory_order mo = m) noexcept
72
+ {
73
+ return std::atomic<T>::fetch_sub (delta, mo);
74
+ }
75
+
76
+ T fetch_and (T mask, std::memory_order mo = m) noexcept
77
+ {
78
+ return std::atomic<T>::fetch_and (mask, mo);
79
+ }
80
+
81
+ T fetch_or (T mask, std::memory_order mo = m) noexcept
82
+ {
83
+ return std::atomic<T>::fetch_or (mask, mo);
84
+ }
85
+
86
+ T fetch_xor (T mask, std::memory_order mo = m) noexcept
87
+ {
88
+ return std::atomic<T>::fetch_xor (mask, mo);
89
+ }
90
+
91
+ // The following operators call non-virtual methods we have overridden above.
92
+ // Hence, we need to override them here as well to allow for a different default memory order.
93
+
94
+ T operator =(T desired) noexcept
95
+ {
96
+ store (desired);
97
+ return desired;
98
+ }
99
+
100
+ operator T () const noexcept
101
+ {
102
+ return load ();
103
+ }
104
+
105
+ T operator +=(T delta) noexcept
106
+ {
107
+ return fetch_add (delta) + delta;
108
+ }
109
+
110
+ T operator -=(T delta) noexcept
111
+ {
112
+ return fetch_sub (delta) - delta;
113
+ }
114
+
115
+ T operator ++() noexcept
116
+ {
117
+ return *this += 1 ;
118
+ }
119
+
120
+ T operator ++(int ) noexcept
121
+ {
122
+ return fetch_add (1 );
123
+ }
124
+
125
+ T operator --() noexcept
126
+ {
127
+ return *this -= 1 ;
128
+ }
129
+
130
+ T operator --(int ) noexcept
131
+ {
132
+ return fetch_sub (1 );
133
+ }
134
+
135
+ T operator &=(T mask) noexcept
136
+ {
137
+ return fetch_and (mask) & mask;
138
+ }
139
+
140
+ T operator |=(T mask) noexcept
141
+ {
142
+ return fetch_or (mask) | mask;
143
+ }
144
+
145
+ T operator ^=(T mask) noexcept
146
+ {
147
+ return fetch_xor (mask) ^ mask;
148
+ }
35
149
};
36
150
37
151
/* *
0 commit comments