1 /*
2     Copyright (c) 2005-2020 Intel Corporation
3 
4     Licensed under the Apache License, Version 2.0 (the "License");
5     you may not use this file except in compliance with the License.
6     You may obtain a copy of the License at
7 
8         http://www.apache.org/licenses/LICENSE-2.0
9 
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15 */
16 
17 #include "internal/_deprecated_header_message_guard.h"
18 
19 #if !defined(__TBB_show_deprecation_message_atomic_H) && defined(__TBB_show_deprecated_header_message)
20 #define  __TBB_show_deprecation_message_atomic_H
21 #pragma message("TBB Warning: tbb/atomic.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
22 #endif
23 
24 #if defined(__TBB_show_deprecated_header_message)
25 #undef __TBB_show_deprecated_header_message
26 #endif
27 
28 #ifndef __TBB_atomic_H
29 #define __TBB_atomic_H
30 
31 #define __TBB_atomic_H_include_area
32 #include "internal/_warning_suppress_enable_notice.h"
33 
34 #include <cstddef>
35 
36 #if _MSC_VER
37 #define __TBB_LONG_LONG __int64
38 #else
39 #define __TBB_LONG_LONG long long
40 #endif /* _MSC_VER */
41 
42 #include "tbb_machine.h"
43 
44 #if _MSC_VER && !__INTEL_COMPILER
45     // Suppress overzealous compiler warnings till the end of the file
46     #pragma warning (push)
47     #pragma warning (disable: 4244 4267 4512)
48 #endif
49 
50 namespace tbb {
51 
52 //! Specifies memory semantics.
53 enum memory_semantics {
54     //! Sequential consistency
55     full_fence,
56     //! Acquire
57     acquire,
58     //! Release
59     release,
60     //! No ordering
61     relaxed
62 };
63 
64 //! @cond INTERNAL
65 namespace internal {
66 
67 #if __TBB_ALIGNAS_PRESENT
68     #define __TBB_DECL_ATOMIC_FIELD(t,f,a) alignas(a) t f;
69 #elif __TBB_ATTRIBUTE_ALIGNED_PRESENT
70     #define __TBB_DECL_ATOMIC_FIELD(t,f,a) t f  __attribute__ ((aligned(a)));
71 #elif __TBB_DECLSPEC_ALIGN_PRESENT
72     #define __TBB_DECL_ATOMIC_FIELD(t,f,a) __declspec(align(a)) t f;
73 #else
74     #error Do not know syntax for forcing alignment.
75 #endif
76 
77 template<size_t S>
78 struct atomic_rep;           // Primary template declared, but never defined.
79 
80 template<>
81 struct atomic_rep<1> {       // Specialization
82     typedef int8_t word;
83 };
84 template<>
85 struct atomic_rep<2> {       // Specialization
86     typedef int16_t word;
87 };
88 template<>
89 struct atomic_rep<4> {       // Specialization
90 #if _MSC_VER && !_WIN64
91     // Work-around that avoids spurious /Wp64 warnings
92     typedef intptr_t word;
93 #else
94     typedef int32_t word;
95 #endif
96 };
97 #if __TBB_64BIT_ATOMICS
98 template<>
99 struct atomic_rep<8> {       // Specialization
100     typedef int64_t word;
101 };
102 #endif
103 
104 template<typename value_type, size_t size>
105 struct aligned_storage;
106 
107 //the specializations are needed to please MSVC syntax of __declspec(align()) which accept _literal_ constants only
108 #if __TBB_ATOMIC_CTORS
109     #define ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(S)                  \
110     template<typename value_type>                                     \
111     struct aligned_storage<value_type,S> {                            \
112         __TBB_DECL_ATOMIC_FIELD(value_type,my_value,S)                \
113         aligned_storage() = default ;                                 \
114         constexpr aligned_storage(value_type value):my_value(value){} \
115     };                                                                \
116 
117 #else
118     #define ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(S)                  \
119     template<typename value_type>                                     \
120     struct aligned_storage<value_type,S> {                            \
121         __TBB_DECL_ATOMIC_FIELD(value_type,my_value,S)                \
122     };                                                                \
123 
124 #endif
125 
126 template<typename value_type>
127 struct aligned_storage<value_type,1> {
128     value_type my_value;
129 #if __TBB_ATOMIC_CTORS
130     aligned_storage() = default ;
131     constexpr aligned_storage(value_type value):my_value(value){}
132 #endif
133 };
134 
135 ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(2)
136 ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(4)
137 #if __TBB_64BIT_ATOMICS
138 ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(8)
139 #endif
140 
141 template<size_t Size, memory_semantics M>
142 struct atomic_traits;        // Primary template declared, but not defined.
143 
144 #define __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(S,M)                                                         \
145     template<> struct atomic_traits<S,M> {                                                               \
146         typedef atomic_rep<S>::word word;                                                                \
147         inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \
148             return __TBB_machine_cmpswp##S##M(location,new_value,comparand);                             \
149         }                                                                                                \
150         inline static word fetch_and_add( volatile void* location, word addend ) {                       \
151             return __TBB_machine_fetchadd##S##M(location,addend);                                        \
152         }                                                                                                \
153         inline static word fetch_and_store( volatile void* location, word value ) {                      \
154             return __TBB_machine_fetchstore##S##M(location,value);                                       \
155         }                                                                                                \
156     };
157 
158 #define __TBB_DECL_ATOMIC_PRIMITIVES(S)                                                                  \
159     template<memory_semantics M>                                                                         \
160     struct atomic_traits<S,M> {                                                                          \
161         typedef atomic_rep<S>::word word;                                                                \
162         inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \
163             return __TBB_machine_cmpswp##S(location,new_value,comparand);                                \
164         }                                                                                                \
165         inline static word fetch_and_add( volatile void* location, word addend ) {                       \
166             return __TBB_machine_fetchadd##S(location,addend);                                           \
167         }                                                                                                \
168         inline static word fetch_and_store( volatile void* location, word value ) {                      \
169             return __TBB_machine_fetchstore##S(location,value);                                          \
170         }                                                                                                \
171     };
172 
173 template<memory_semantics M>
174 struct atomic_load_store_traits;    // Primary template declaration
175 
176 #define __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(M)                      \
177     template<> struct atomic_load_store_traits<M> {                     \
178         template <typename T>                                           \
179         inline static T load( const volatile T& location ) {            \
180             return __TBB_load_##M( location );                          \
181         }                                                               \
182         template <typename T>                                           \
183         inline static void store( volatile T& location, T value ) {     \
184             __TBB_store_##M( location, value );                         \
185         }                                                               \
186     }
187 
188 #if __TBB_USE_FENCED_ATOMICS
189 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,full_fence)
190 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,full_fence)
191 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,full_fence)
192 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,acquire)
193 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,acquire)
194 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,acquire)
195 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,release)
196 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,release)
197 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,release)
198 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,relaxed)
199 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,relaxed)
200 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,relaxed)
201 #if __TBB_64BIT_ATOMICS
202 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,full_fence)
203 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,acquire)
204 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,release)
205 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,relaxed)
206 #endif
207 #else /* !__TBB_USE_FENCED_ATOMICS */
208 __TBB_DECL_ATOMIC_PRIMITIVES(1)
209 __TBB_DECL_ATOMIC_PRIMITIVES(2)
210 __TBB_DECL_ATOMIC_PRIMITIVES(4)
211 #if __TBB_64BIT_ATOMICS
212 __TBB_DECL_ATOMIC_PRIMITIVES(8)
213 #endif
214 #endif /* !__TBB_USE_FENCED_ATOMICS */
215 
216 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(full_fence);
217 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(acquire);
218 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(release);
219 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(relaxed);
220 
221 //! Additive inverse of 1 for type T.
222 /** Various compilers issue various warnings if -1 is used with various integer types.
223     The baroque expression below avoids all the warnings (we hope). */
224 #define __TBB_MINUS_ONE(T) (T(T(0)-T(1)))
225 
226 //! Base class that provides basic functionality for atomic<T> without fetch_and_add.
227 /** Works for any type T that has the same size as an integral type, has a trivial constructor/destructor,
228     and can be copied/compared by memcpy/memcmp. */
229 template<typename T>
230 struct atomic_impl {
231 protected:
232     aligned_storage<T,sizeof(T)> my_storage;
233 private:
234     //TODO: rechecks on recent versions of gcc if union is still the _only_ way to do a conversion without warnings
235     //! Union type used to convert type T to underlying integral type.
236     template<typename value_type>
237     union converter {
238         typedef typename atomic_rep<sizeof(value_type)>::word bits_type;
239         converter(){}
240         converter(value_type a_value) : value(a_value) {}
241         value_type value;
242         bits_type bits;
243     };
244 
245     template<typename value_t>
246     static typename converter<value_t>::bits_type to_bits(value_t value){
247         return converter<value_t>(value).bits;
248     }
249     template<typename value_t>
250     static value_t to_value(typename converter<value_t>::bits_type bits){
251         converter<value_t> u;
252         u.bits = bits;
253         return u.value;
254     }
255 
256     template<typename value_t>
257     union ptr_converter;            //Primary template declared, but never defined.
258 
259     template<typename value_t>
260     union ptr_converter<value_t *> {
261         ptr_converter(){}
262         ptr_converter(value_t* a_value) : value(a_value) {}
263         value_t* value;
264         uintptr_t bits;
265     };
266     //TODO: check if making to_bits accepting reference (thus unifying it with to_bits_ref)
267     //does not hurt performance
268     template<typename value_t>
269     static typename converter<value_t>::bits_type & to_bits_ref(value_t& value){
270         //TODO: this #ifdef is temporary workaround, as union conversion seems to fail
271         //on suncc for 64 bit types for 32 bit target
272         #if !__SUNPRO_CC
273             return *(typename converter<value_t>::bits_type*)ptr_converter<value_t*>(&value).bits;
274         #else
275             return *(typename converter<value_t>::bits_type*)(&value);
276         #endif
277     }
278 
279 
280 public:
281     typedef T value_type;
282 
283 #if __TBB_ATOMIC_CTORS
284     atomic_impl() = default ;
285     constexpr atomic_impl(value_type value):my_storage(value){}
286 #endif
287     template<memory_semantics M>
288     value_type fetch_and_store( value_type value ) {
289           return to_value<value_type>(
290                   internal::atomic_traits<sizeof(value_type),M>::fetch_and_store( &my_storage.my_value, to_bits(value) )
291           );
292     }
293 
294     value_type fetch_and_store( value_type value ) {
295         return fetch_and_store<full_fence>(value);
296     }
297 
298     template<memory_semantics M>
299     value_type compare_and_swap( value_type value, value_type comparand ) {
300         return to_value<value_type>(
301                 internal::atomic_traits<sizeof(value_type),M>::compare_and_swap( &my_storage.my_value, to_bits(value), to_bits(comparand) )
302         );
303     }
304 
305     value_type compare_and_swap( value_type value, value_type comparand ) {
306         return compare_and_swap<full_fence>(value,comparand);
307     }
308 
309     operator value_type() const volatile {                // volatile qualifier here for backwards compatibility
310         return  to_value<value_type>(
311                 __TBB_load_with_acquire( to_bits_ref(my_storage.my_value) )
312         );
313     }
314 
315     template<memory_semantics M>
316     value_type load () const {
317         return to_value<value_type>(
318                 internal::atomic_load_store_traits<M>::load( to_bits_ref(my_storage.my_value) )
319         );
320     }
321 
322     value_type load () const {
323         return load<acquire>();
324     }
325 
326     template<memory_semantics M>
327     void store ( value_type value ) {
328         internal::atomic_load_store_traits<M>::store( to_bits_ref(my_storage.my_value), to_bits(value));
329     }
330 
331     void store ( value_type value ) {
332         store<release>( value );
333     }
334 
335 protected:
336     value_type store_with_release( value_type rhs ) {
337        //TODO: unify with store<release>
338         __TBB_store_with_release( to_bits_ref(my_storage.my_value), to_bits(rhs) );
339         return rhs;
340     }
341 };
342 
343 //! Base class that provides basic functionality for atomic<T> with fetch_and_add.
344 /** I is the underlying type.
345     D is the difference type.
346     StepType should be char if I is an integral type, and T if I is a T*. */
347 template<typename I, typename D, typename StepType>
348 struct atomic_impl_with_arithmetic: atomic_impl<I> {
349 public:
350     typedef I value_type;
351 #if    __TBB_ATOMIC_CTORS
352     atomic_impl_with_arithmetic() = default ;
353     constexpr atomic_impl_with_arithmetic(value_type value): atomic_impl<I>(value){}
354 #endif
355     template<memory_semantics M>
356     value_type fetch_and_add( D addend ) {
357         return value_type(internal::atomic_traits<sizeof(value_type),M>::fetch_and_add( &this->my_storage.my_value, addend*sizeof(StepType) ));
358     }
359 
360     value_type fetch_and_add( D addend ) {
361         return fetch_and_add<full_fence>(addend);
362     }
363 
364     template<memory_semantics M>
365     value_type fetch_and_increment() {
366         return fetch_and_add<M>(1);
367     }
368 
369     value_type fetch_and_increment() {
370         return fetch_and_add(1);
371     }
372 
373     template<memory_semantics M>
374     value_type fetch_and_decrement() {
375         return fetch_and_add<M>(__TBB_MINUS_ONE(D));
376     }
377 
378     value_type fetch_and_decrement() {
379         return fetch_and_add(__TBB_MINUS_ONE(D));
380     }
381 
382 public:
383     value_type operator+=( D value ) {
384         return fetch_and_add(value)+value;
385     }
386 
387     value_type operator-=( D value ) {
388         // Additive inverse of value computed using binary minus,
389         // instead of unary minus, for sake of avoiding compiler warnings.
390         return operator+=(D(0)-value);
391     }
392 
393     value_type operator++() {
394         return fetch_and_add(1)+1;
395     }
396 
397     value_type operator--() {
398         return fetch_and_add(__TBB_MINUS_ONE(D))-1;
399     }
400 
401     value_type operator++(int) {
402         return fetch_and_add(1);
403     }
404 
405     value_type operator--(int) {
406         return fetch_and_add(__TBB_MINUS_ONE(D));
407     }
408 };
409 
410 } /* Internal */
411 //! @endcond
412 
413 //! Primary template for atomic.
414 /** See the Reference for details.
415     @ingroup synchronization */
416 template<typename T>
417 struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic")
418 atomic: internal::atomic_impl<T> {
419 #if __TBB_ATOMIC_CTORS
420     atomic() = default;
421     constexpr atomic(T arg): internal::atomic_impl<T>(arg) {}
422     constexpr atomic<T>(const atomic<T>& rhs): internal::atomic_impl<T>(rhs) {}
423 #endif
424     T operator=( T rhs ) {
425         // "this" required here in strict ISO C++ because store_with_release is a dependent name
426         return this->store_with_release(rhs);
427     }
428     atomic<T>& operator=( const atomic<T>& rhs ) {this->store_with_release(rhs); return *this;}
429 };
430 
431 #if __TBB_ATOMIC_CTORS
432     #define __TBB_DECL_ATOMIC(T)                                                                    \
433         template<> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic")  \
434         atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {                                \
435             atomic() = default;                                                                     \
436             constexpr atomic(T arg): internal::atomic_impl_with_arithmetic<T,T,char>(arg) {}        \
437             constexpr atomic<T>(const atomic<T>& rhs):                                              \
438                       internal::atomic_impl_with_arithmetic<T,T,char>(rhs) {}                       \
439                                                                                                     \
440             T operator=( T rhs ) {return store_with_release(rhs);}                                  \
441             atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}   \
442         };
443 #else
444     #define __TBB_DECL_ATOMIC(T)                                                                    \
445         template<> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic")  \
446         atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {                                \
447             T operator=( T rhs ) {return store_with_release(rhs);}                                  \
448             atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}   \
449         };
450 #endif
451 
452 #if __TBB_64BIT_ATOMICS
453 //TODO: consider adding non-default (and atomic) copy constructor for 32bit platform
454 __TBB_DECL_ATOMIC(__TBB_LONG_LONG)
455 __TBB_DECL_ATOMIC(unsigned __TBB_LONG_LONG)
456 #else
457 // test_atomic will verify that sizeof(long long)==8
458 #endif
459 __TBB_DECL_ATOMIC(long)
460 __TBB_DECL_ATOMIC(unsigned long)
461 
462 #if _MSC_VER && !_WIN64
463 #if __TBB_ATOMIC_CTORS
464 /* Special version of __TBB_DECL_ATOMIC that avoids gratuitous warnings from cl /Wp64 option.
465    It is identical to __TBB_DECL_ATOMIC(unsigned) except that it replaces operator=(T)
466    with an operator=(U) that explicitly converts the U to a T.  Types T and U should be
467    type synonyms on the platform.  Type U should be the wider variant of T from the
468    perspective of /Wp64. */
469 #define __TBB_DECL_ATOMIC_ALT(T,U) \
470     template<> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic") \
471     atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {                               \
472         atomic() = default ;                                                                   \
473         constexpr atomic(T arg): internal::atomic_impl_with_arithmetic<T,T,char>(arg) {}       \
474         constexpr atomic<T>(const atomic<T>& rhs):                                             \
475                   internal::atomic_impl_with_arithmetic<T,T,char>(rhs) {}                      \
476                                                                                                \
477         T operator=( U rhs ) {return store_with_release(T(rhs));}                              \
478         atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}  \
479     };
480 #else
481 #define __TBB_DECL_ATOMIC_ALT(T,U) \
482     template<> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic") \
483     atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {                               \
484         T operator=( U rhs ) {return store_with_release(T(rhs));}                              \
485         atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}  \
486     };
487 #endif
488 __TBB_DECL_ATOMIC_ALT(unsigned,size_t)
489 __TBB_DECL_ATOMIC_ALT(int,ptrdiff_t)
490 #else
491 __TBB_DECL_ATOMIC(unsigned)
492 __TBB_DECL_ATOMIC(int)
493 #endif /* _MSC_VER && !_WIN64 */
494 
495 __TBB_DECL_ATOMIC(unsigned short)
496 __TBB_DECL_ATOMIC(short)
497 __TBB_DECL_ATOMIC(char)
498 __TBB_DECL_ATOMIC(signed char)
499 __TBB_DECL_ATOMIC(unsigned char)
500 
501 #if !_MSC_VER || defined(_NATIVE_WCHAR_T_DEFINED)
502 __TBB_DECL_ATOMIC(wchar_t)
503 #endif /* _MSC_VER||!defined(_NATIVE_WCHAR_T_DEFINED) */
504 
505 //! Specialization for atomic<T*> with arithmetic and operator->.
506 template<typename T> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic")
507 atomic<T*>: internal::atomic_impl_with_arithmetic<T*,ptrdiff_t,T> {
508 #if __TBB_ATOMIC_CTORS
509     atomic() = default ;
510     constexpr atomic(T* arg): internal::atomic_impl_with_arithmetic<T*,ptrdiff_t,T>(arg) {}
511     constexpr atomic(const atomic<T*>& rhs): internal::atomic_impl_with_arithmetic<T*,ptrdiff_t,T>(rhs) {}
512 #endif
513     T* operator=( T* rhs ) {
514         // "this" required here in strict ISO C++ because store_with_release is a dependent name
515         return this->store_with_release(rhs);
516     }
517     atomic<T*>& operator=( const atomic<T*>& rhs ) {
518         this->store_with_release(rhs); return *this;
519     }
520     T* operator->() const {
521         return (*this);
522     }
523 };
524 
525 //! Specialization for atomic<void*>, for sake of not allowing arithmetic or operator->.
526 template<> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic")
527 atomic<void*>: internal::atomic_impl<void*> {
528 #if __TBB_ATOMIC_CTORS
529     atomic() = default ;
530     constexpr atomic(void* arg): internal::atomic_impl<void*>(arg) {}
531     constexpr atomic(const atomic<void*>& rhs): internal::atomic_impl<void*>(rhs) {}
532 #endif
533     void* operator=( void* rhs ) {
534         // "this" required here in strict ISO C++ because store_with_release is a dependent name
535         return this->store_with_release(rhs);
536     }
537     atomic<void*>& operator=( const atomic<void*>& rhs ) {
538         this->store_with_release(rhs); return *this;
539     }
540 };
541 
542 // Helpers to workaround ugly syntax of calling template member function of a
543 // template class with template argument dependent on template parameters.
544 
545 template <memory_semantics M, typename T>
546 T load ( const atomic<T>& a ) { return a.template load<M>(); }
547 
548 template <memory_semantics M, typename T>
549 void store ( atomic<T>& a, T value ) { a.template store<M>(value); }
550 
551 namespace interface6{
552 //! Make an atomic for use in an initialization (list), as an alternative to zero-initialization or normal assignment.
553 template<typename T>
554 atomic<T> make_atomic(T t) {
555     atomic<T> a;
556     store<relaxed>(a,t);
557     return a;
558 }
559 }
560 using interface6::make_atomic;
561 
562 namespace internal {
563 template<memory_semantics M, typename T >
564 void swap(atomic<T> & lhs, atomic<T> & rhs){
565     T tmp = load<M>(lhs);
566     store<M>(lhs,load<M>(rhs));
567     store<M>(rhs,tmp);
568 }
569 
570 // only to aid in the gradual conversion of ordinary variables to proper atomics
571 template<typename T>
572 inline atomic<T>& as_atomic( T& t ) {
573     return (atomic<T>&)t;
574 }
575 } // namespace tbb::internal
576 
577 } // namespace tbb
578 
579 #if _MSC_VER && !__INTEL_COMPILER
580     #pragma warning (pop)
581 #endif // warnings are restored
582 
583 #include "internal/_warning_suppress_disable_notice.h"
584 #undef __TBB_atomic_H_include_area
585 
586 #endif /* __TBB_atomic_H */
587