File indexing completed on 2025-01-18 10:12:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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
0041
0042 #include "tbb_machine.h"
0043
0044 #if _MSC_VER && !__INTEL_COMPILER
0045
0046 #pragma warning (push)
0047 #pragma warning (disable: 4244 4267 4512)
0048 #endif
0049
0050 namespace tbb {
0051
0052
0053 enum memory_semantics {
0054
0055 full_fence,
0056
0057 acquire,
0058
0059 release,
0060
0061 relaxed
0062 };
0063
0064
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;
0079
0080 template<>
0081 struct atomic_rep<1> {
0082 typedef int8_t word;
0083 };
0084 template<>
0085 struct atomic_rep<2> {
0086 typedef int16_t word;
0087 };
0088 template<>
0089 struct atomic_rep<4> {
0090 #if _MSC_VER && !_WIN64
0091
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> {
0100 typedef int64_t word;
0101 };
0102 #endif
0103
0104 template<typename value_type, size_t size>
0105 struct aligned_storage;
0106
0107
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;
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;
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
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
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
0222
0223
0224 #define __TBB_MINUS_ONE(T) (T(T(0)-T(1)))
0225
0226
0227
0228
0229 template<typename T>
0230 struct atomic_impl {
0231 protected:
0232 aligned_storage<T,sizeof(T)> my_storage;
0233 private:
0234
0235
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;
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
0267
0268 template<typename value_t>
0269 static typename converter<value_t>::bits_type & to_bits_ref(value_t& value){
0270
0271
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 {
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
0338 __TBB_store_with_release( to_bits_ref(my_storage.my_value), to_bits(rhs) );
0339 return rhs;
0340 }
0341 };
0342
0343
0344
0345
0346
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
0389
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 }
0411
0412
0413
0414
0415
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
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
0454 __TBB_DECL_ATOMIC(__TBB_LONG_LONG)
0455 __TBB_DECL_ATOMIC(unsigned __TBB_LONG_LONG)
0456 #else
0457
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
0465
0466
0467
0468
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
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
0504
0505
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
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
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
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
0543
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
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
0571 template<typename T>
0572 inline atomic<T>& as_atomic( T& t ) {
0573 return (atomic<T>&)t;
0574 }
0575 }
0576
0577 }
0578
0579 #if _MSC_VER && !__INTEL_COMPILER
0580 #pragma warning (pop)
0581 #endif
0582
0583 #include "internal/_warning_suppress_disable_notice.h"
0584 #undef __TBB_atomic_H_include_area
0585
0586 #endif