Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:12:51

0001 /*
0002     Copyright (c) 2005-2020 Intel Corporation
0003 
0004     Licensed under the Apache License, Version 2.0 (the "License");
0005     you may not use this file except in compliance with the License.
0006     You may obtain a copy of the License at
0007 
0008         http://www.apache.org/licenses/LICENSE-2.0
0009 
0010     Unless required by applicable law or agreed to in writing, software
0011     distributed under the License is distributed on an "AS IS" BASIS,
0012     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013     See the License for the specific language governing permissions and
0014     limitations under the License.
0015 */
0016 
0017 #include "internal/_deprecated_header_message_guard.h"
0018 
0019 #if !defined(__TBB_show_deprecation_message_atomic_H) && defined(__TBB_show_deprecated_header_message)
0020 #define  __TBB_show_deprecation_message_atomic_H
0021 #pragma message("TBB Warning: tbb/atomic.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
0022 #endif
0023 
0024 #if defined(__TBB_show_deprecated_header_message)
0025 #undef __TBB_show_deprecated_header_message
0026 #endif
0027 
0028 #ifndef __TBB_atomic_H
0029 #define __TBB_atomic_H
0030 
0031 #define __TBB_atomic_H_include_area
0032 #include "internal/_warning_suppress_enable_notice.h"
0033 
0034 #include <cstddef>
0035 
0036 #if _MSC_VER
0037 #define __TBB_LONG_LONG __int64
0038 #else
0039 #define __TBB_LONG_LONG long long
0040 #endif /* _MSC_VER */
0041 
0042 #include "tbb_machine.h"
0043 
0044 #if _MSC_VER && !__INTEL_COMPILER
0045     // Suppress overzealous compiler warnings till the end of the file
0046     #pragma warning (push)
0047     #pragma warning (disable: 4244 4267 4512)
0048 #endif
0049 
0050 namespace tbb {
0051 
0052 //! Specifies memory semantics.
0053 enum memory_semantics {
0054     //! Sequential consistency
0055     full_fence,
0056     //! Acquire
0057     acquire,
0058     //! Release
0059     release,
0060     //! No ordering
0061     relaxed
0062 };
0063 
0064 //! @cond INTERNAL
0065 namespace internal {
0066 
0067 #if __TBB_ALIGNAS_PRESENT
0068     #define __TBB_DECL_ATOMIC_FIELD(t,f,a) alignas(a) t f;
0069 #elif __TBB_ATTRIBUTE_ALIGNED_PRESENT
0070     #define __TBB_DECL_ATOMIC_FIELD(t,f,a) t f  __attribute__ ((aligned(a)));
0071 #elif __TBB_DECLSPEC_ALIGN_PRESENT
0072     #define __TBB_DECL_ATOMIC_FIELD(t,f,a) __declspec(align(a)) t f;
0073 #else
0074     #error Do not know syntax for forcing alignment.
0075 #endif
0076 
0077 template<size_t S>
0078 struct atomic_rep;           // Primary template declared, but never defined.
0079 
0080 template<>
0081 struct atomic_rep<1> {       // Specialization
0082     typedef int8_t word;
0083 };
0084 template<>
0085 struct atomic_rep<2> {       // Specialization
0086     typedef int16_t word;
0087 };
0088 template<>
0089 struct atomic_rep<4> {       // Specialization
0090 #if _MSC_VER && !_WIN64
0091     // Work-around that avoids spurious /Wp64 warnings
0092     typedef intptr_t word;
0093 #else
0094     typedef int32_t word;
0095 #endif
0096 };
0097 #if __TBB_64BIT_ATOMICS
0098 template<>
0099 struct atomic_rep<8> {       // Specialization
0100     typedef int64_t word;
0101 };
0102 #endif
0103 
0104 template<typename value_type, size_t size>
0105 struct aligned_storage;
0106 
0107 //the specializations are needed to please MSVC syntax of __declspec(align()) which accept _literal_ constants only
0108 #if __TBB_ATOMIC_CTORS
0109     #define ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(S)                  \
0110     template<typename value_type>                                     \
0111     struct aligned_storage<value_type,S> {                            \
0112         __TBB_DECL_ATOMIC_FIELD(value_type,my_value,S)                \
0113         aligned_storage() = default ;                                 \
0114         constexpr aligned_storage(value_type value):my_value(value){} \
0115     };                                                                \
0116 
0117 #else
0118     #define ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(S)                  \
0119     template<typename value_type>                                     \
0120     struct aligned_storage<value_type,S> {                            \
0121         __TBB_DECL_ATOMIC_FIELD(value_type,my_value,S)                \
0122     };                                                                \
0123 
0124 #endif
0125 
0126 template<typename value_type>
0127 struct aligned_storage<value_type,1> {
0128     value_type my_value;
0129 #if __TBB_ATOMIC_CTORS
0130     aligned_storage() = default ;
0131     constexpr aligned_storage(value_type value):my_value(value){}
0132 #endif
0133 };
0134 
0135 ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(2)
0136 ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(4)
0137 #if __TBB_64BIT_ATOMICS
0138 ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(8)
0139 #endif
0140 
0141 template<size_t Size, memory_semantics M>
0142 struct atomic_traits;        // Primary template declared, but not defined.
0143 
0144 #define __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(S,M)                                                         \
0145     template<> struct atomic_traits<S,M> {                                                               \
0146         typedef atomic_rep<S>::word word;                                                                \
0147         inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \
0148             return __TBB_machine_cmpswp##S##M(location,new_value,comparand);                             \
0149         }                                                                                                \
0150         inline static word fetch_and_add( volatile void* location, word addend ) {                       \
0151             return __TBB_machine_fetchadd##S##M(location,addend);                                        \
0152         }                                                                                                \
0153         inline static word fetch_and_store( volatile void* location, word value ) {                      \
0154             return __TBB_machine_fetchstore##S##M(location,value);                                       \
0155         }                                                                                                \
0156     };
0157 
0158 #define __TBB_DECL_ATOMIC_PRIMITIVES(S)                                                                  \
0159     template<memory_semantics M>                                                                         \
0160     struct atomic_traits<S,M> {                                                                          \
0161         typedef atomic_rep<S>::word word;                                                                \
0162         inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \
0163             return __TBB_machine_cmpswp##S(location,new_value,comparand);                                \
0164         }                                                                                                \
0165         inline static word fetch_and_add( volatile void* location, word addend ) {                       \
0166             return __TBB_machine_fetchadd##S(location,addend);                                           \
0167         }                                                                                                \
0168         inline static word fetch_and_store( volatile void* location, word value ) {                      \
0169             return __TBB_machine_fetchstore##S(location,value);                                          \
0170         }                                                                                                \
0171     };
0172 
0173 template<memory_semantics M>
0174 struct atomic_load_store_traits;    // Primary template declaration
0175 
0176 #define __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(M)                      \
0177     template<> struct atomic_load_store_traits<M> {                     \
0178         template <typename T>                                           \
0179         inline static T load( const volatile T& location ) {            \
0180             return __TBB_load_##M( location );                          \
0181         }                                                               \
0182         template <typename T>                                           \
0183         inline static void store( volatile T& location, T value ) {     \
0184             __TBB_store_##M( location, value );                         \
0185         }                                                               \
0186     }
0187 
0188 #if __TBB_USE_FENCED_ATOMICS
0189 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,full_fence)
0190 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,full_fence)
0191 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,full_fence)
0192 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,acquire)
0193 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,acquire)
0194 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,acquire)
0195 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,release)
0196 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,release)
0197 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,release)
0198 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,relaxed)
0199 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,relaxed)
0200 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,relaxed)
0201 #if __TBB_64BIT_ATOMICS
0202 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,full_fence)
0203 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,acquire)
0204 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,release)
0205 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,relaxed)
0206 #endif
0207 #else /* !__TBB_USE_FENCED_ATOMICS */
0208 __TBB_DECL_ATOMIC_PRIMITIVES(1)
0209 __TBB_DECL_ATOMIC_PRIMITIVES(2)
0210 __TBB_DECL_ATOMIC_PRIMITIVES(4)
0211 #if __TBB_64BIT_ATOMICS
0212 __TBB_DECL_ATOMIC_PRIMITIVES(8)
0213 #endif
0214 #endif /* !__TBB_USE_FENCED_ATOMICS */
0215 
0216 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(full_fence);
0217 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(acquire);
0218 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(release);
0219 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(relaxed);
0220 
0221 //! Additive inverse of 1 for type T.
0222 /** Various compilers issue various warnings if -1 is used with various integer types.
0223     The baroque expression below avoids all the warnings (we hope). */
0224 #define __TBB_MINUS_ONE(T) (T(T(0)-T(1)))
0225 
0226 //! Base class that provides basic functionality for atomic<T> without fetch_and_add.
0227 /** Works for any type T that has the same size as an integral type, has a trivial constructor/destructor,
0228     and can be copied/compared by memcpy/memcmp. */
0229 template<typename T>
0230 struct atomic_impl {
0231 protected:
0232     aligned_storage<T,sizeof(T)> my_storage;
0233 private:
0234     //TODO: rechecks on recent versions of gcc if union is still the _only_ way to do a conversion without warnings
0235     //! Union type used to convert type T to underlying integral type.
0236     template<typename value_type>
0237     union converter {
0238         typedef typename atomic_rep<sizeof(value_type)>::word bits_type;
0239         converter(){}
0240         converter(value_type a_value) : value(a_value) {}
0241         value_type value;
0242         bits_type bits;
0243     };
0244 
0245     template<typename value_t>
0246     static typename converter<value_t>::bits_type to_bits(value_t value){
0247         return converter<value_t>(value).bits;
0248     }
0249     template<typename value_t>
0250     static value_t to_value(typename converter<value_t>::bits_type bits){
0251         converter<value_t> u;
0252         u.bits = bits;
0253         return u.value;
0254     }
0255 
0256     template<typename value_t>
0257     union ptr_converter;            //Primary template declared, but never defined.
0258 
0259     template<typename value_t>
0260     union ptr_converter<value_t *> {
0261         ptr_converter(){}
0262         ptr_converter(value_t* a_value) : value(a_value) {}
0263         value_t* value;
0264         uintptr_t bits;
0265     };
0266     //TODO: check if making to_bits accepting reference (thus unifying it with to_bits_ref)
0267     //does not hurt performance
0268     template<typename value_t>
0269     static typename converter<value_t>::bits_type & to_bits_ref(value_t& value){
0270         //TODO: this #ifdef is temporary workaround, as union conversion seems to fail
0271         //on suncc for 64 bit types for 32 bit target
0272         #if !__SUNPRO_CC
0273             return *(typename converter<value_t>::bits_type*)ptr_converter<value_t*>(&value).bits;
0274         #else
0275             return *(typename converter<value_t>::bits_type*)(&value);
0276         #endif
0277     }
0278 
0279 
0280 public:
0281     typedef T value_type;
0282 
0283 #if __TBB_ATOMIC_CTORS
0284     atomic_impl() = default ;
0285     constexpr atomic_impl(value_type value):my_storage(value){}
0286 #endif
0287     template<memory_semantics M>
0288     value_type fetch_and_store( value_type value ) {
0289           return to_value<value_type>(
0290                   internal::atomic_traits<sizeof(value_type),M>::fetch_and_store( &my_storage.my_value, to_bits(value) )
0291           );
0292     }
0293 
0294     value_type fetch_and_store( value_type value ) {
0295         return fetch_and_store<full_fence>(value);
0296     }
0297 
0298     template<memory_semantics M>
0299     value_type compare_and_swap( value_type value, value_type comparand ) {
0300         return to_value<value_type>(
0301                 internal::atomic_traits<sizeof(value_type),M>::compare_and_swap( &my_storage.my_value, to_bits(value), to_bits(comparand) )
0302         );
0303     }
0304 
0305     value_type compare_and_swap( value_type value, value_type comparand ) {
0306         return compare_and_swap<full_fence>(value,comparand);
0307     }
0308 
0309     operator value_type() const volatile {                // volatile qualifier here for backwards compatibility
0310         return  to_value<value_type>(
0311                 __TBB_load_with_acquire( to_bits_ref(my_storage.my_value) )
0312         );
0313     }
0314 
0315     template<memory_semantics M>
0316     value_type load () const {
0317         return to_value<value_type>(
0318                 internal::atomic_load_store_traits<M>::load( to_bits_ref(my_storage.my_value) )
0319         );
0320     }
0321 
0322     value_type load () const {
0323         return load<acquire>();
0324     }
0325 
0326     template<memory_semantics M>
0327     void store ( value_type value ) {
0328         internal::atomic_load_store_traits<M>::store( to_bits_ref(my_storage.my_value), to_bits(value));
0329     }
0330 
0331     void store ( value_type value ) {
0332         store<release>( value );
0333     }
0334 
0335 protected:
0336     value_type store_with_release( value_type rhs ) {
0337        //TODO: unify with store<release>
0338         __TBB_store_with_release( to_bits_ref(my_storage.my_value), to_bits(rhs) );
0339         return rhs;
0340     }
0341 };
0342 
0343 //! Base class that provides basic functionality for atomic<T> with fetch_and_add.
0344 /** I is the underlying type.
0345     D is the difference type.
0346     StepType should be char if I is an integral type, and T if I is a T*. */
0347 template<typename I, typename D, typename StepType>
0348 struct atomic_impl_with_arithmetic: atomic_impl<I> {
0349 public:
0350     typedef I value_type;
0351 #if    __TBB_ATOMIC_CTORS
0352     atomic_impl_with_arithmetic() = default ;
0353     constexpr atomic_impl_with_arithmetic(value_type value): atomic_impl<I>(value){}
0354 #endif
0355     template<memory_semantics M>
0356     value_type fetch_and_add( D addend ) {
0357         return value_type(internal::atomic_traits<sizeof(value_type),M>::fetch_and_add( &this->my_storage.my_value, addend*sizeof(StepType) ));
0358     }
0359 
0360     value_type fetch_and_add( D addend ) {
0361         return fetch_and_add<full_fence>(addend);
0362     }
0363 
0364     template<memory_semantics M>
0365     value_type fetch_and_increment() {
0366         return fetch_and_add<M>(1);
0367     }
0368 
0369     value_type fetch_and_increment() {
0370         return fetch_and_add(1);
0371     }
0372 
0373     template<memory_semantics M>
0374     value_type fetch_and_decrement() {
0375         return fetch_and_add<M>(__TBB_MINUS_ONE(D));
0376     }
0377 
0378     value_type fetch_and_decrement() {
0379         return fetch_and_add(__TBB_MINUS_ONE(D));
0380     }
0381 
0382 public:
0383     value_type operator+=( D value ) {
0384         return fetch_and_add(value)+value;
0385     }
0386 
0387     value_type operator-=( D value ) {
0388         // Additive inverse of value computed using binary minus,
0389         // instead of unary minus, for sake of avoiding compiler warnings.
0390         return operator+=(D(0)-value);
0391     }
0392 
0393     value_type operator++() {
0394         return fetch_and_add(1)+1;
0395     }
0396 
0397     value_type operator--() {
0398         return fetch_and_add(__TBB_MINUS_ONE(D))-1;
0399     }
0400 
0401     value_type operator++(int) {
0402         return fetch_and_add(1);
0403     }
0404 
0405     value_type operator--(int) {
0406         return fetch_and_add(__TBB_MINUS_ONE(D));
0407     }
0408 };
0409 
0410 } /* Internal */
0411 //! @endcond
0412 
0413 //! Primary template for atomic.
0414 /** See the Reference for details.
0415     @ingroup synchronization */
0416 template<typename T>
0417 struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic")
0418 atomic: internal::atomic_impl<T> {
0419 #if __TBB_ATOMIC_CTORS
0420     atomic() = default;
0421     constexpr atomic(T arg): internal::atomic_impl<T>(arg) {}
0422     constexpr atomic<T>(const atomic<T>& rhs): internal::atomic_impl<T>(rhs) {}
0423 #endif
0424     T operator=( T rhs ) {
0425         // "this" required here in strict ISO C++ because store_with_release is a dependent name
0426         return this->store_with_release(rhs);
0427     }
0428     atomic<T>& operator=( const atomic<T>& rhs ) {this->store_with_release(rhs); return *this;}
0429 };
0430 
0431 #if __TBB_ATOMIC_CTORS
0432     #define __TBB_DECL_ATOMIC(T)                                                                    \
0433         template<> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic")  \
0434         atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {                                \
0435             atomic() = default;                                                                     \
0436             constexpr atomic(T arg): internal::atomic_impl_with_arithmetic<T,T,char>(arg) {}        \
0437             constexpr atomic<T>(const atomic<T>& rhs):                                              \
0438                       internal::atomic_impl_with_arithmetic<T,T,char>(rhs) {}                       \
0439                                                                                                     \
0440             T operator=( T rhs ) {return store_with_release(rhs);}                                  \
0441             atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}   \
0442         };
0443 #else
0444     #define __TBB_DECL_ATOMIC(T)                                                                    \
0445         template<> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic")  \
0446         atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {                                \
0447             T operator=( T rhs ) {return store_with_release(rhs);}                                  \
0448             atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}   \
0449         };
0450 #endif
0451 
0452 #if __TBB_64BIT_ATOMICS
0453 //TODO: consider adding non-default (and atomic) copy constructor for 32bit platform
0454 __TBB_DECL_ATOMIC(__TBB_LONG_LONG)
0455 __TBB_DECL_ATOMIC(unsigned __TBB_LONG_LONG)
0456 #else
0457 // test_atomic will verify that sizeof(long long)==8
0458 #endif
0459 __TBB_DECL_ATOMIC(long)
0460 __TBB_DECL_ATOMIC(unsigned long)
0461 
0462 #if _MSC_VER && !_WIN64
0463 #if __TBB_ATOMIC_CTORS
0464 /* Special version of __TBB_DECL_ATOMIC that avoids gratuitous warnings from cl /Wp64 option.
0465    It is identical to __TBB_DECL_ATOMIC(unsigned) except that it replaces operator=(T)
0466    with an operator=(U) that explicitly converts the U to a T.  Types T and U should be
0467    type synonyms on the platform.  Type U should be the wider variant of T from the
0468    perspective of /Wp64. */
0469 #define __TBB_DECL_ATOMIC_ALT(T,U) \
0470     template<> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic") \
0471     atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {                               \
0472         atomic() = default ;                                                                   \
0473         constexpr atomic(T arg): internal::atomic_impl_with_arithmetic<T,T,char>(arg) {}       \
0474         constexpr atomic<T>(const atomic<T>& rhs):                                             \
0475                   internal::atomic_impl_with_arithmetic<T,T,char>(rhs) {}                      \
0476                                                                                                \
0477         T operator=( U rhs ) {return store_with_release(T(rhs));}                              \
0478         atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}  \
0479     };
0480 #else
0481 #define __TBB_DECL_ATOMIC_ALT(T,U) \
0482     template<> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic") \
0483     atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {                               \
0484         T operator=( U rhs ) {return store_with_release(T(rhs));}                              \
0485         atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}  \
0486     };
0487 #endif
0488 __TBB_DECL_ATOMIC_ALT(unsigned,size_t)
0489 __TBB_DECL_ATOMIC_ALT(int,ptrdiff_t)
0490 #else
0491 __TBB_DECL_ATOMIC(unsigned)
0492 __TBB_DECL_ATOMIC(int)
0493 #endif /* _MSC_VER && !_WIN64 */
0494 
0495 __TBB_DECL_ATOMIC(unsigned short)
0496 __TBB_DECL_ATOMIC(short)
0497 __TBB_DECL_ATOMIC(char)
0498 __TBB_DECL_ATOMIC(signed char)
0499 __TBB_DECL_ATOMIC(unsigned char)
0500 
0501 #if !_MSC_VER || defined(_NATIVE_WCHAR_T_DEFINED)
0502 __TBB_DECL_ATOMIC(wchar_t)
0503 #endif /* _MSC_VER||!defined(_NATIVE_WCHAR_T_DEFINED) */
0504 
0505 //! Specialization for atomic<T*> with arithmetic and operator->.
0506 template<typename T> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic")
0507 atomic<T*>: internal::atomic_impl_with_arithmetic<T*,ptrdiff_t,T> {
0508 #if __TBB_ATOMIC_CTORS
0509     atomic() = default ;
0510     constexpr atomic(T* arg): internal::atomic_impl_with_arithmetic<T*,ptrdiff_t,T>(arg) {}
0511     constexpr atomic(const atomic<T*>& rhs): internal::atomic_impl_with_arithmetic<T*,ptrdiff_t,T>(rhs) {}
0512 #endif
0513     T* operator=( T* rhs ) {
0514         // "this" required here in strict ISO C++ because store_with_release is a dependent name
0515         return this->store_with_release(rhs);
0516     }
0517     atomic<T*>& operator=( const atomic<T*>& rhs ) {
0518         this->store_with_release(rhs); return *this;
0519     }
0520     T* operator->() const {
0521         return (*this);
0522     }
0523 };
0524 
0525 //! Specialization for atomic<void*>, for sake of not allowing arithmetic or operator->.
0526 template<> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic")
0527 atomic<void*>: internal::atomic_impl<void*> {
0528 #if __TBB_ATOMIC_CTORS
0529     atomic() = default ;
0530     constexpr atomic(void* arg): internal::atomic_impl<void*>(arg) {}
0531     constexpr atomic(const atomic<void*>& rhs): internal::atomic_impl<void*>(rhs) {}
0532 #endif
0533     void* operator=( void* rhs ) {
0534         // "this" required here in strict ISO C++ because store_with_release is a dependent name
0535         return this->store_with_release(rhs);
0536     }
0537     atomic<void*>& operator=( const atomic<void*>& rhs ) {
0538         this->store_with_release(rhs); return *this;
0539     }
0540 };
0541 
0542 // Helpers to workaround ugly syntax of calling template member function of a
0543 // template class with template argument dependent on template parameters.
0544 
0545 template <memory_semantics M, typename T>
0546 T load ( const atomic<T>& a ) { return a.template load<M>(); }
0547 
0548 template <memory_semantics M, typename T>
0549 void store ( atomic<T>& a, T value ) { a.template store<M>(value); }
0550 
0551 namespace interface6{
0552 //! Make an atomic for use in an initialization (list), as an alternative to zero-initialization or normal assignment.
0553 template<typename T>
0554 atomic<T> make_atomic(T t) {
0555     atomic<T> a;
0556     store<relaxed>(a,t);
0557     return a;
0558 }
0559 }
0560 using interface6::make_atomic;
0561 
0562 namespace internal {
0563 template<memory_semantics M, typename T >
0564 void swap(atomic<T> & lhs, atomic<T> & rhs){
0565     T tmp = load<M>(lhs);
0566     store<M>(lhs,load<M>(rhs));
0567     store<M>(rhs,tmp);
0568 }
0569 
0570 // only to aid in the gradual conversion of ordinary variables to proper atomics
0571 template<typename T>
0572 inline atomic<T>& as_atomic( T& t ) {
0573     return (atomic<T>&)t;
0574 }
0575 } // namespace tbb::internal
0576 
0577 } // namespace tbb
0578 
0579 #if _MSC_VER && !__INTEL_COMPILER
0580     #pragma warning (pop)
0581 #endif // warnings are restored
0582 
0583 #include "internal/_warning_suppress_disable_notice.h"
0584 #undef __TBB_atomic_H_include_area
0585 
0586 #endif /* __TBB_atomic_H */