Intel(R) Threading Building Blocks Doxygen Documentation version 4.2.3
Loading...
Searching...
No Matches
atomic.h
Go to the documentation of this file.
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
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
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
50namespace tbb {
51
62};
63
65namespace 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
77template<size_t S>
78struct atomic_rep; // Primary template declared, but never defined.
79
80template<>
81struct atomic_rep<1> { // Specialization
82 typedef int8_t word;
83};
84template<>
85struct atomic_rep<2> { // Specialization
86 typedef int16_t word;
87};
88template<>
89struct 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
98template<>
99struct atomic_rep<8> { // Specialization
100 typedef int64_t word;
101};
102#endif
103
104template<typename value_type, size_t size>
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
126template<typename value_type>
127struct 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
137#if __TBB_64BIT_ATOMICS
139#endif
140
141template<size_t Size, memory_semantics M>
142struct 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
173template<memory_semantics M>
174struct 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
201#if __TBB_64BIT_ATOMICS
206#endif
207#else /* !__TBB_USE_FENCED_ATOMICS */
211#if __TBB_64BIT_ATOMICS
213#endif
214#endif /* !__TBB_USE_FENCED_ATOMICS */
215
220
222
224#define __TBB_MINUS_ONE(T) (T(T(0)-T(1)))
225
227
229template<typename T>
231protected:
233private:
234 //TODO: rechecks on recent versions of gcc if union is still the _only_ way to do a conversion without warnings
236 template<typename value_type>
237 union converter {
238 typedef typename atomic_rep<sizeof(value_type)>::word bits_type;
240 converter(value_type a_value) : value(a_value) {}
243 };
244
245 template<typename value_t>
248 }
249 template<typename value_t>
250 static value_t to_value(typename converter<value_t>::bits_type bits){
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 *> {
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>
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
274 #else
275 return *(typename converter<value_t>::bits_type*)(&value);
276 #endif
277 }
278
279
280public:
281 typedef T value_type;
282
283#if __TBB_ATOMIC_CTORS
284 atomic_impl() = default ;
286#endif
287 template<memory_semantics M>
289 return to_value<value_type>(
291 );
292 }
293
295 return fetch_and_store<full_fence>(value);
296 }
297
298 template<memory_semantics M>
300 return to_value<value_type>(
302 );
303 }
304
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>(
312 );
313 }
314
315 template<memory_semantics M>
316 value_type load () const {
317 return to_value<value_type>(
319 );
320 }
321
322 value_type load () const {
323 return load<acquire>();
324 }
325
326 template<memory_semantics M>
329 }
330
332 store<release>( value );
333 }
334
335protected:
337 //TODO: unify with store<release>
339 return rhs;
340 }
341};
342
344
347template<typename I, typename D, typename StepType>
349public:
350 typedef I value_type;
351#if __TBB_ATOMIC_CTORS
354#endif
355 template<memory_semantics M>
357 return value_type(internal::atomic_traits<sizeof(value_type),M>::fetch_and_add( &this->my_storage.my_value, addend*sizeof(StepType) ));
358 }
359
361 return fetch_and_add<full_fence>(addend);
362 }
363
364 template<memory_semantics M>
366 return fetch_and_add<M>(1);
367 }
368
370 return fetch_and_add(1);
371 }
372
373 template<memory_semantics M>
375 return fetch_and_add<M>(__TBB_MINUS_ONE(D));
376 }
377
380 }
381
382public:
384 return fetch_and_add(value)+value;
385 }
386
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
394 return fetch_and_add(1)+1;
395 }
396
398 return fetch_and_add(__TBB_MINUS_ONE(D))-1;
399 }
400
402 return fetch_and_add(1);
403 }
404
407 }
408};
409
410} /* Internal */
412
414
416template<typename T>
417struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic")
418atomic: 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
456#else
457// test_atomic will verify that sizeof(long long)==8
458#endif
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)
493#endif /* _MSC_VER && !_WIN64 */
494
495__TBB_DECL_ATOMIC(unsigned short)
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
506template<typename T> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic")
507atomic<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
526template<> struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic")
527atomic<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
545template <memory_semantics M, typename T>
546T load ( const atomic<T>& a ) { return a.template load<M>(); }
547
548template <memory_semantics M, typename T>
549void store ( atomic<T>& a, T value ) { a.template store<M>(value); }
550
551namespace interface6{
553template<typename T>
554atomic<T> make_atomic(T t) {
555 atomic<T> a;
556 store<relaxed>(a,t);
557 return a;
558}
559}
561
562namespace internal {
563template<memory_semantics M, typename T >
564void 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
571template<typename T>
572inline 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
584#undef __TBB_atomic_H_include_area
585
586#endif /* __TBB_atomic_H */
#define __TBB_LONG_LONG
Definition atomic.h:39
#define ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(S)
Definition atomic.h:109
#define __TBB_DECL_ATOMIC_PRIMITIVES(S)
Definition atomic.h:158
#define __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(M)
Definition atomic.h:176
#define __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(S, M)
Definition atomic.h:144
#define __TBB_MINUS_ONE(T)
Additive inverse of 1 for type T.
Definition atomic.h:224
#define __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG(msg)
Definition tbb_config.h:648
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long value
#define __TBB_DECL_ATOMIC(T)
Primary template for atomic.
Definition atomic.h:432
The graph class.
void store(atomic< T > &a, T value)
Definition atomic.h:549
struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic") atomic< T * > struct __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::atomic is deprecated, use std::atomic") atomic< void * > T load(const atomic< T > &a)
Specialization for atomic<T*> with arithmetic and operator->.
Definition atomic.h:546
memory_semantics
Specifies memory semantics.
Definition atomic.h:53
@ release
Release.
Definition atomic.h:59
@ full_fence
Sequential consistency.
Definition atomic.h:55
@ relaxed
No ordering.
Definition atomic.h:61
@ acquire
Acquire.
Definition atomic.h:57
atomic< T > make_atomic(T t)
Make an atomic for use in an initialization (list), as an alternative to zero-initialization or norma...
Definition atomic.h:554
T __TBB_load_with_acquire(const volatile T &location)
void swap(atomic< T > &lhs, atomic< T > &rhs)
Definition atomic.h:564
atomic< T > & as_atomic(T &t)
Definition atomic.h:572
void __TBB_store_with_release(volatile T &location, V value)
constexpr aligned_storage(value_type value)
Definition atomic.h:131
Base class that provides basic functionality for atomic<T> without fetch_and_add.
Definition atomic.h:230
static converter< value_t >::bits_type & to_bits_ref(value_t &value)
Definition atomic.h:269
static value_t to_value(typename converter< value_t >::bits_type bits)
Definition atomic.h:250
value_type load() const
Definition atomic.h:316
static converter< value_t >::bits_type to_bits(value_t value)
Definition atomic.h:246
value_type compare_and_swap(value_type value, value_type comparand)
Definition atomic.h:305
value_type load() const
Definition atomic.h:322
value_type compare_and_swap(value_type value, value_type comparand)
Definition atomic.h:299
void store(value_type value)
Definition atomic.h:331
value_type fetch_and_store(value_type value)
Definition atomic.h:288
value_type fetch_and_store(value_type value)
Definition atomic.h:294
aligned_storage< T, sizeof(T)> my_storage
Definition atomic.h:232
constexpr atomic_impl(value_type value)
Definition atomic.h:285
value_type store_with_release(value_type rhs)
Definition atomic.h:336
void store(value_type value)
Definition atomic.h:327
Union type used to convert type T to underlying integral type.
Definition atomic.h:237
converter(value_type a_value)
Definition atomic.h:240
atomic_rep< sizeof(value_type)>::word bits_type
Definition atomic.h:238
Base class that provides basic functionality for atomic<T> with fetch_and_add.
Definition atomic.h:348
constexpr atomic_impl_with_arithmetic(value_type value)
Definition atomic.h:353

Copyright © 2005-2020 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.