@@ -58,122 +58,57 @@ class AtomicValue {
5858 base::AtomicWord value_;
5959};
6060
61- class AsAtomic32 {
61+ // Provides atomic operations for a values stored at some address.
62+ template <typename TAtomicStorageType>
63+ class AsAtomicImpl {
6264 public:
63- template <typename T>
64- static T Acquire_Load (T* addr) {
65- STATIC_ASSERT (sizeof (T) <= sizeof (base::Atomic32));
66- return to_return_type<T>(base::Acquire_Load (to_storage_addr (addr)));
67- }
68-
69- template <typename T>
70- static T Relaxed_Load (T* addr) {
71- STATIC_ASSERT (sizeof (T) <= sizeof (base::Atomic32));
72- return to_return_type<T>(base::Relaxed_Load (to_storage_addr (addr)));
73- }
74-
75- template <typename T>
76- static void Release_Store (T* addr,
77- typename std::remove_reference<T>::type new_value) {
78- STATIC_ASSERT (sizeof (T) <= sizeof (base::Atomic32));
79- base::Release_Store (to_storage_addr (addr), to_storage_type (new_value));
80- }
81-
82- template <typename T>
83- static void Relaxed_Store (T* addr,
84- typename std::remove_reference<T>::type new_value) {
85- STATIC_ASSERT (sizeof (T) <= sizeof (base::Atomic32));
86- base::Relaxed_Store (to_storage_addr (addr), to_storage_type (new_value));
87- }
65+ using AtomicStorageType = TAtomicStorageType;
8866
89- template <typename T>
90- static T Release_CompareAndSwap (
91- T* addr, typename std::remove_reference<T>::type old_value,
92- typename std::remove_reference<T>::type new_value) {
93- STATIC_ASSERT (sizeof (T) <= sizeof (base::Atomic32));
94- return to_return_type<T>(base::Release_CompareAndSwap (
95- to_storage_addr (addr), to_storage_type (old_value),
96- to_storage_type (new_value)));
97- }
98-
99- // Atomically sets bits selected by the mask to the given value.
100- // Returns false if the bits are already set as needed.
101- template <typename T>
102- static bool SetBits (T* addr, T bits, T mask) {
103- STATIC_ASSERT (sizeof (T) <= sizeof (base::Atomic32));
104- DCHECK_EQ (bits & ~mask, static_cast <T>(0 ));
105- T old_value;
106- T new_value;
107- do {
108- old_value = Relaxed_Load (addr);
109- if ((old_value & mask) == bits) return false ;
110- new_value = (old_value & ~mask) | bits;
111- } while (Release_CompareAndSwap (addr, old_value, new_value) != old_value);
112- return true ;
113- }
114-
115- private:
116- template <typename T>
117- static base::Atomic32 to_storage_type (T value) {
118- return static_cast <base::Atomic32>(value);
119- }
120- template <typename T>
121- static T to_return_type (base::Atomic32 value) {
122- return static_cast <T>(value);
123- }
124- template <typename T>
125- static base::Atomic32* to_storage_addr (T* value) {
126- return reinterpret_cast <base::Atomic32*>(value);
127- }
128- template <typename T>
129- static const base::Atomic32* to_storage_addr (const T* value) {
130- return reinterpret_cast <const base::Atomic32*>(value);
131- }
132- };
133-
134- class AsAtomicWord {
135- public:
13667 template <typename T>
13768 static T Acquire_Load (T* addr) {
138- STATIC_ASSERT (sizeof (T) <= sizeof (base::AtomicWord));
139- return to_return_type<T>(base::Acquire_Load (to_storage_addr (addr)));
69+ STATIC_ASSERT (sizeof (T) <= sizeof (AtomicStorageType));
70+ return cast_helper<T>::to_return_type (
71+ base::Acquire_Load (to_storage_addr (addr)));
14072 }
14173
14274 template <typename T>
14375 static T Relaxed_Load (T* addr) {
144- STATIC_ASSERT (sizeof (T) <= sizeof (base::AtomicWord));
145- return to_return_type<T>(base::Relaxed_Load (to_storage_addr (addr)));
76+ STATIC_ASSERT (sizeof (T) <= sizeof (AtomicStorageType));
77+ return cast_helper<T>::to_return_type (
78+ base::Relaxed_Load (to_storage_addr (addr)));
14679 }
14780
14881 template <typename T>
14982 static void Release_Store (T* addr,
15083 typename std::remove_reference<T>::type new_value) {
151- STATIC_ASSERT (sizeof (T) <= sizeof (base::AtomicWord));
152- base::Release_Store (to_storage_addr (addr), to_storage_type (new_value));
84+ STATIC_ASSERT (sizeof (T) <= sizeof (AtomicStorageType));
85+ base::Release_Store (to_storage_addr (addr),
86+ cast_helper<T>::to_storage_type (new_value));
15387 }
15488
15589 template <typename T>
15690 static void Relaxed_Store (T* addr,
15791 typename std::remove_reference<T>::type new_value) {
158- STATIC_ASSERT (sizeof (T) <= sizeof (base::AtomicWord));
159- base::Relaxed_Store (to_storage_addr (addr), to_storage_type (new_value));
92+ STATIC_ASSERT (sizeof (T) <= sizeof (AtomicStorageType));
93+ base::Relaxed_Store (to_storage_addr (addr),
94+ cast_helper<T>::to_storage_type (new_value));
16095 }
16196
16297 template <typename T>
16398 static T Release_CompareAndSwap (
16499 T* addr, typename std::remove_reference<T>::type old_value,
165100 typename std::remove_reference<T>::type new_value) {
166- STATIC_ASSERT (sizeof (T) <= sizeof (base::AtomicWord ));
167- return to_return_type <T>(base::Release_CompareAndSwap (
168- to_storage_addr (addr), to_storage_type (old_value),
169- to_storage_type (new_value)));
101+ STATIC_ASSERT (sizeof (T) <= sizeof (AtomicStorageType ));
102+ return cast_helper <T>:: to_return_type (base::Release_CompareAndSwap (
103+ to_storage_addr (addr), cast_helper<T>:: to_storage_type (old_value),
104+ cast_helper<T>:: to_storage_type (new_value)));
170105 }
171106
172107 // Atomically sets bits selected by the mask to the given value.
173108 // Returns false if the bits are already set as needed.
174109 template <typename T>
175110 static bool SetBits (T* addr, T bits, T mask) {
176- STATIC_ASSERT (sizeof (T) <= sizeof (base::AtomicWord ));
111+ STATIC_ASSERT (sizeof (T) <= sizeof (AtomicStorageType ));
177112 DCHECK_EQ (bits & ~mask, static_cast <T>(0 ));
178113 T old_value;
179114 T new_value;
@@ -186,138 +121,51 @@ class AsAtomicWord {
186121 }
187122
188123 private:
189- template <typename T>
190- static base::AtomicWord to_storage_type (T value) {
191- return static_cast <base::AtomicWord>(value);
192- }
193- template <typename T>
194- static T to_return_type (base::AtomicWord value) {
195- return static_cast <T>(value);
196- }
197- template <typename T>
198- static base::AtomicWord* to_storage_addr (T* value) {
199- return reinterpret_cast <base::AtomicWord*>(value);
200- }
201- template <typename T>
202- static const base::AtomicWord* to_storage_addr (const T* value) {
203- return reinterpret_cast <const base::AtomicWord*>(value);
204- }
205- };
206-
207- class AsAtomic8 {
208- public:
209- template <typename T>
210- static T Acquire_Load (T* addr) {
211- STATIC_ASSERT (sizeof (T) <= sizeof (base::Atomic8));
212- return to_return_type<T>(base::Acquire_Load (to_storage_addr (addr)));
213- }
214-
215- template <typename T>
216- static T Relaxed_Load (T* addr) {
217- STATIC_ASSERT (sizeof (T) <= sizeof (base::Atomic8));
218- return to_return_type<T>(base::Relaxed_Load (to_storage_addr (addr)));
219- }
220-
221- template <typename T>
222- static void Release_Store (T* addr,
223- typename std::remove_reference<T>::type new_value) {
224- STATIC_ASSERT (sizeof (T) <= sizeof (base::Atomic8));
225- base::Release_Store (to_storage_addr (addr), to_storage_type (new_value));
226- }
227-
228- template <typename T>
229- static void Relaxed_Store (T* addr,
230- typename std::remove_reference<T>::type new_value) {
231- STATIC_ASSERT (sizeof (T) <= sizeof (base::Atomic8));
232- base::Relaxed_Store (to_storage_addr (addr), to_storage_type (new_value));
233- }
124+ template <typename U>
125+ struct cast_helper {
126+ static AtomicStorageType to_storage_type (U value) {
127+ return static_cast <AtomicStorageType>(value);
128+ }
129+ static U to_return_type (AtomicStorageType value) {
130+ return static_cast <U>(value);
131+ }
132+ };
234133
235- template <typename T >
236- static T Release_CompareAndSwap (
237- T* addr, typename std::remove_reference<T>::type old_value,
238- typename std::remove_reference<T>::type new_value) {
239- STATIC_ASSERT ( sizeof (T) <= sizeof (base::Atomic8));
240- return to_return_type<T>( base::Release_CompareAndSwap (
241- to_storage_addr (addr), to_storage_type (old_value),
242- to_storage_type (new_value)));
243- }
134+ template <typename U >
135+ struct cast_helper <U*> {
136+ static AtomicStorageType to_storage_type (U* value) {
137+ return reinterpret_cast <AtomicStorageType>(value);
138+ }
139+ static U* to_return_type (AtomicStorageType value) {
140+ return reinterpret_cast <U*>(value);
141+ }
142+ };
244143
245- private:
246- template <typename T>
247- static base::Atomic8 to_storage_type (T value) {
248- return static_cast <base::Atomic8>(value);
249- }
250144 template <typename T>
251- static T to_return_type (base::Atomic8 value) {
252- return static_cast <T >(value);
145+ static AtomicStorageType* to_storage_addr (T* value) {
146+ return reinterpret_cast <AtomicStorageType* >(value);
253147 }
254148 template <typename T>
255- static base::Atomic8* to_storage_addr (T* value) {
256- return reinterpret_cast <base::Atomic8*>(value);
257- }
258- template <typename T>
259- static const base::Atomic8* to_storage_addr (const T* value) {
260- return reinterpret_cast <const base::Atomic8*>(value);
149+ static const AtomicStorageType* to_storage_addr (const T* value) {
150+ return reinterpret_cast <const AtomicStorageType*>(value);
261151 }
262152};
263153
264- class AsAtomicPointer {
265- public:
266- template <typename T>
267- static T Acquire_Load (T* addr) {
268- STATIC_ASSERT (sizeof (T) <= sizeof (base::AtomicWord));
269- return to_return_type<T>(base::Acquire_Load (to_storage_addr (addr)));
270- }
271-
272- template <typename T>
273- static T Relaxed_Load (T* addr) {
274- STATIC_ASSERT (sizeof (T) <= sizeof (base::AtomicWord));
275- return to_return_type<T>(base::Relaxed_Load (to_storage_addr (addr)));
276- }
277-
278- template <typename T>
279- static void Release_Store (T* addr,
280- typename std::remove_reference<T>::type new_value) {
281- STATIC_ASSERT (sizeof (T) <= sizeof (base::AtomicWord));
282- base::Release_Store (to_storage_addr (addr), to_storage_type (new_value));
283- }
284-
285- template <typename T>
286- static void Relaxed_Store (T* addr,
287- typename std::remove_reference<T>::type new_value) {
288- STATIC_ASSERT (sizeof (T) <= sizeof (base::AtomicWord));
289- base::Relaxed_Store (to_storage_addr (addr), to_storage_type (new_value));
290- }
291-
292- template <typename T>
293- static T Release_CompareAndSwap (
294- T* addr, typename std::remove_reference<T>::type old_value,
295- typename std::remove_reference<T>::type new_value) {
296- STATIC_ASSERT (sizeof (T) <= sizeof (base::AtomicWord));
297- return to_return_type<T>(base::Release_CompareAndSwap (
298- to_storage_addr (addr), to_storage_type (old_value),
299- to_storage_type (new_value)));
300- }
154+ using AsAtomic8 = AsAtomicImpl<base::Atomic8>;
155+ using AsAtomic32 = AsAtomicImpl<base::Atomic32>;
156+ using AsAtomicWord = AsAtomicImpl<base::AtomicWord>;
301157
302- private:
303- template <typename T>
304- static base::AtomicWord to_storage_type (T value) {
305- return reinterpret_cast <base::AtomicWord>(value);
306- }
307- template <typename T>
308- static T to_return_type (base::AtomicWord value) {
309- return reinterpret_cast <T>(value);
310- }
311- template <typename T>
312- static base::AtomicWord* to_storage_addr (T* value) {
313- return reinterpret_cast <base::AtomicWord*>(value);
314- }
158+ // This is similar to AsAtomicWord but it explicitly deletes functionality
159+ // provided atomic access to bit representation of stored values.
160+ template <typename TAtomicStorageType>
161+ class AsAtomicPointerImpl : public AsAtomicImpl <TAtomicStorageType> {
162+ public:
315163 template <typename T>
316- static const base::AtomicWord* to_storage_addr (const T* value) {
317- return reinterpret_cast <const base::AtomicWord*>(value);
318- }
164+ static bool SetBits (T* addr, T bits, T mask) = delete;
319165};
320166
167+ using AsAtomicPointer = AsAtomicPointerImpl<base::AtomicWord>;
168+
321169template <typename T,
322170 typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
323171inline void CheckedIncrement (std::atomic<T>* number, T amount) {
0 commit comments