- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

# atomic.h

    00001 /*
    00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
    00003
    00004     This file is part of Threading Building Blocks.
    00005
    00006     Threading Building Blocks is free software; you can redistribute it
    00007     and/or modify it under the terms of the GNU General Public License
    00008     version 2 as published by the Free Software Foundation.
    00009
    00010     Threading Building Blocks is distributed in the hope that it will be
    00011     useful, but WITHOUT ANY WARRANTY; without even the implied warranty
    00012     of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00013     GNU General Public License for more details.
    00014
    00015     You should have received a copy of the GNU General Public License
    00016     along with Threading Building Blocks; if not, write to the Free Software
    00017     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    00018
    00019     As a special exception, you may use this file as part of a free software
    00020     library without restriction.  Specifically, if other files instantiate
    00021     templates or use macros or inline functions from this file, or you compile
    00022     this file and link it with other files to produce an executable, this
    00023     file does not by itself cause the resulting executable to be covered by
    00024     the GNU General Public License.  This exception does not however
    00025     invalidate any other reasons why the executable file might be covered by
    00026     the GNU General Public License.
    00027 */
    00028
    00029 #ifndef __TBB_atomic_H
    00030 #define __TBB_atomic_H
    00031
    00032 #include "tbb_stddef.h"
    00033 #include <cstddef>
    00034
    00035 #if _MSC_VER
    00036 #define __TBB_LONG_LONG __int64
    00037 #else
    00038 #define __TBB_LONG_LONG long long
    00039 #endif /* _MSC_VER */
    00040
    00041 #include "tbb_machine.h"
    00042
    00043 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
    00044     // Workaround for overzealous compiler warnings
    00045     #pragma warning (push)
    00046     #pragma warning (disable: 4244 4267)
    00047 #endif
    00048
    00049 namespace tbb {
    00050
    00052 enum memory_semantics {
    00054     full_fence,
    00056     acquire,
    00058     release,
    00060     relaxed
    00061 };
    00062
    00064 namespace internal {
    00065
    00066 #if __TBB_ATTRIBUTE_ALIGNED_PRESENT
    00067     #define __TBB_DECL_ATOMIC_FIELD(t,f,a) t f  __attribute__ ((aligned(a)));
    00068 #elif __TBB_DECLSPEC_ALIGN_PRESENT
    00069     #define __TBB_DECL_ATOMIC_FIELD(t,f,a) __declspec(align(a)) t f;
    00070 #else
    00071     #error Do not know syntax for forcing alignment.
    00072 #endif
    00073
    00074 template<size_t S>
    00075 struct atomic_rep;           // Primary template declared, but never defined.
    00076
    00077 template<>
    00078 struct atomic_rep<1> {       // Specialization
    00079     typedef int8_t word;
    00080     int8_t value;
    00081 };
    00082 template<>
    00083 struct atomic_rep<2> {       // Specialization
    00084     typedef int16_t word;
    00085     __TBB_DECL_ATOMIC_FIELD(int16_t,value,2)
    00086 };
    00087 template<>
    00088 struct atomic_rep<4> {       // Specialization
    00089 #if _MSC_VER && !_WIN64
    00090     // Work-around that avoids spurious /Wp64 warnings
    00091     typedef intptr_t word;
    00092 #else
    00093     typedef int32_t word;
    00094 #endif
    00095     __TBB_DECL_ATOMIC_FIELD(int32_t,value,4)
    00096 };
    00097 #if __TBB_64BIT_ATOMICS
    00098 template<>
    00099 struct atomic_rep<8> {       // Specialization
    00100     typedef int64_t word;
    00101     __TBB_DECL_ATOMIC_FIELD(int64_t,value,8)
    00102 };
    00103 #endif
    00104
    00105 template<size_t Size, memory_semantics M>
    00106 struct atomic_traits;        // Primary template declared, but not defined.
    00107
    00108 #define __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(S,M)                                                         \
    00109     template<> struct atomic_traits<S,M> {                                                               \
    00110         typedef atomic_rep<S>::word word;                                                                \
    00111         inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \
    00112             return __TBB_machine_cmpswp##S##M(location,new_value,comparand);                             \
    00113         }                                                                                                \
    00114         inline static word fetch_and_add( volatile void* location, word addend ) {                       \
    00115             return __TBB_machine_fetchadd##S##M(location,addend);                                        \
    00116         }                                                                                                \
    00117         inline static word fetch_and_store( volatile void* location, word value ) {                      \
    00118             return __TBB_machine_fetchstore##S##M(location,value);                                       \
    00119         }                                                                                                \
    00120     };
    00121
    00122 #define __TBB_DECL_ATOMIC_PRIMITIVES(S)                                                                  \
    00123     template<memory_semantics M>                                                                         \
    00124     struct atomic_traits<S,M> {                                                                          \
    00125         typedef atomic_rep<S>::word word;                                                                \
    00126         inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \
    00127             return __TBB_machine_cmpswp##S(location,new_value,comparand);                                \
    00128         }                                                                                                \
    00129         inline static word fetch_and_add( volatile void* location, word addend ) {                       \
    00130             return __TBB_machine_fetchadd##S(location,addend);                                           \
    00131         }                                                                                                \
    00132         inline static word fetch_and_store( volatile void* location, word value ) {                      \
    00133             return __TBB_machine_fetchstore##S(location,value);                                          \
    00134         }                                                                                                \
    00135     };
    00136
    00137 template<memory_semantics M>
    00138 struct atomic_load_store_traits;    // Primary template declaration
    00139
    00140 #define __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(M)                      \
    00141     template<> struct atomic_load_store_traits<M> {                     \
    00142         template <typename T>                                           \
    00143         inline static T load( const volatile T& location ) {            \
    00144             return __TBB_load_##M( location );                          \
    00145         }                                                               \
    00146         template <typename T>                                           \
    00147         inline static void store( volatile T& location, T value ) {     \
    00148             __TBB_store_##M( location, value );                         \
    00149         }                                                               \
    00150     }
    00151
    00152 #if __TBB_USE_FENCED_ATOMICS
    00153 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,full_fence)
    00154 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,full_fence)
    00155 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,full_fence)
    00156 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,acquire)
    00157 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,acquire)
    00158 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,acquire)
    00159 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,release)
    00160 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,release)
    00161 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,release)
    00162 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,relaxed)
    00163 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,relaxed)
    00164 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,relaxed)
    00165 #if __TBB_64BIT_ATOMICS
    00166 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,full_fence)
    00167 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,acquire)
    00168 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,release)
    00169 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,relaxed)
    00170 #endif
    00171 #else /* !__TBB_USE_FENCED_ATOMICS */
    00172 __TBB_DECL_ATOMIC_PRIMITIVES(1)
    00173 __TBB_DECL_ATOMIC_PRIMITIVES(2)
    00174 __TBB_DECL_ATOMIC_PRIMITIVES(4)
    00175 #if __TBB_64BIT_ATOMICS
    00176 __TBB_DECL_ATOMIC_PRIMITIVES(8)
    00177 #endif
    00178 #endif /* !__TBB_USE_FENCED_ATOMICS */
    00179
    00180 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(full_fence);
    00181 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(acquire);
    00182 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(release);
    00183 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(relaxed);
    00184
    00186
    00188 #define __TBB_MINUS_ONE(T) (T(T(0)-T(1)))
    00189
    00191
    00193 template<typename T>
    00194 struct atomic_impl {
    00195 protected:
    00196     atomic_rep<sizeof(T)> rep;
    00197 private:
    00199     union converter {
    00200         T value;
    00201         typename atomic_rep<sizeof(T)>::word bits;
    00202     };
    00203 public:
    00204     typedef T value_type;
    00205
    00206     template<memory_semantics M>
    00207     value_type fetch_and_store( value_type value ) {
    00208         converter u, w;
    00209         u.value = value;
    00210         w.bits = internal::atomic_traits<sizeof(value_type),M>::fetch_and_store(&rep.value,u.bits);
    00211         return w.value;
    00212     }
    00213
    00214     value_type fetch_and_store( value_type value ) {
    00215         return fetch_and_store<full_fence>(value);
    00216     }
    00217
    00218     template<memory_semantics M>
    00219     value_type compare_and_swap( value_type value, value_type comparand ) {
    00220         converter u, v, w;
    00221         u.value = value;
    00222         v.value = comparand;
    00223         w.bits = internal::atomic_traits<sizeof(value_type),M>::compare_and_swap(&rep.value,u.bits,v.bits);
    00224         return w.value;
    00225     }
    00226
    00227     value_type compare_and_swap( value_type value, value_type comparand ) {
    00228         return compare_and_swap<full_fence>(value,comparand);
    00229     }
    00230
    00231     operator value_type() const volatile {                // volatile qualifier here for backwards compatibility
    00232         converter w;
    00233         w.bits = __TBB_load_with_acquire( rep.value );
    00234         return w.value;
    00235     }
    00236
    00237     template<memory_semantics M>
    00238     value_type load () const {
    00239         converter u;
    00240         u.bits = internal::atomic_load_store_traits<M>::load( rep.value );
    00241         return u.value;
    00242     }
    00243
    00244     value_type load () const {
    00245         return load<acquire>();
    00246     }
    00247
    00248     template<memory_semantics M>
    00249     void store ( value_type value ) {
    00250         converter u;
    00251         u.value = value;
    00252         internal::atomic_load_store_traits<M>::store( rep.value, u.bits );
    00253     }
    00254
    00255     void store ( value_type value ) {
    00256         store<release>( value );
    00257     }
    00258
    00259 protected:
    00260     value_type store_with_release( value_type rhs ) {
    00261         converter u;
    00262         u.value = rhs;
    00263         __TBB_store_with_release(rep.value,u.bits);
    00264         return rhs;
    00265     }
    00266 };
    00267
    00269
    00272 template<typename I, typename D, typename StepType>
    00273 struct atomic_impl_with_arithmetic: atomic_impl<I> {
    00274 public:
    00275     typedef I value_type;
    00276
    00277     template<memory_semantics M>
    00278     value_type fetch_and_add( D addend ) {
    00279         return value_type(internal::atomic_traits<sizeof(value_type),M>::fetch_and_add( &this->rep.value, addend*sizeof(StepType) ));
    00280     }
    00281
    00282     value_type fetch_and_add( D addend ) {
    00283         return fetch_and_add<full_fence>(addend);
    00284     }
    00285
    00286     template<memory_semantics M>
    00287     value_type fetch_and_increment() {
    00288         return fetch_and_add<M>(1);
    00289     }
    00290
    00291     value_type fetch_and_increment() {
    00292         return fetch_and_add(1);
    00293     }
    00294
    00295     template<memory_semantics M>
    00296     value_type fetch_and_decrement() {
    00297         return fetch_and_add<M>(__TBB_MINUS_ONE(D));
    00298     }
    00299
    00300     value_type fetch_and_decrement() {
    00301         return fetch_and_add(__TBB_MINUS_ONE(D));
    00302     }
    00303
    00304 public:
    00305     value_type operator+=( D value ) {
    00306         return fetch_and_add(value)+value;
    00307     }
    00308
    00309     value_type operator-=( D value ) {
    00310         // Additive inverse of value computed using binary minus,
    00311         // instead of unary minus, for sake of avoiding compiler warnings.
    00312         return operator+=(D(0)-value);
    00313     }
    00314
    00315     value_type operator++() {
    00316         return fetch_and_add(1)+1;
    00317     }
    00318
    00319     value_type operator--() {
    00320         return fetch_and_add(__TBB_MINUS_ONE(D))-1;
    00321     }
    00322
    00323     value_type operator++(int) {
    00324         return fetch_and_add(1);
    00325     }
    00326
    00327     value_type operator--(int) {
    00328         return fetch_and_add(__TBB_MINUS_ONE(D));
    00329     }
    00330 };
    00331
    00332 } /* Internal */
    00334
    00336
    00338 template<typename T>
    00339 struct atomic: internal::atomic_impl<T> {
    00340     T operator=( T rhs ) {
    00341         // "this" required here in strict ISO C++ because store_with_release is a dependent name
    00342         return this->store_with_release(rhs);
    00343     }
    00344     atomic<T>& operator=( const atomic<T>& rhs ) {this->store_with_release(rhs); return *this;}
    00345 };
    00346
    00347 #define __TBB_DECL_ATOMIC(T) \
    00348     template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {  \
    00349         T operator=( T rhs ) {return store_with_release(rhs);}  \
    00350         atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}  \
    00351     };
    00352
    00353 #if __TBB_64BIT_ATOMICS
    00354 __TBB_DECL_ATOMIC(__TBB_LONG_LONG)
    00355 __TBB_DECL_ATOMIC(unsigned __TBB_LONG_LONG)
    00356 #else
    00357 // test_atomic will verify that sizeof(long long)==8
    00358 #endif
    00359 __TBB_DECL_ATOMIC(long)
    00360 __TBB_DECL_ATOMIC(unsigned long)
    00361
    00362 #if _MSC_VER && !_WIN64
    00363 /* Special version of __TBB_DECL_ATOMIC that avoids gratuitous warnings from cl /Wp64 option.
    00364    It is identical to __TBB_DECL_ATOMIC(unsigned) except that it replaces operator=(T)
    00365    with an operator=(U) that explicitly converts the U to a T.  Types T and U should be
    00366    type synonyms on the platform.  Type U should be the wider variant of T from the
    00367    perspective of /Wp64. */
    00368 #define __TBB_DECL_ATOMIC_ALT(T,U) \
    00369     template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {  \
    00370         T operator=( U rhs ) {return store_with_release(T(rhs));}  \
    00371         atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}  \
    00372     };
    00373 __TBB_DECL_ATOMIC_ALT(unsigned,size_t)
    00374 __TBB_DECL_ATOMIC_ALT(int,ptrdiff_t)
    00375 #else
    00376 __TBB_DECL_ATOMIC(unsigned)
    00377 __TBB_DECL_ATOMIC(int)
    00378 #endif /* _MSC_VER && !_WIN64 */
    00379
    00380 __TBB_DECL_ATOMIC(unsigned short)
    00381 __TBB_DECL_ATOMIC(short)
    00382 __TBB_DECL_ATOMIC(char)
    00383 __TBB_DECL_ATOMIC(signed char)
    00384 __TBB_DECL_ATOMIC(unsigned char)
    00385
    00386 #if !_MSC_VER || defined(_NATIVE_WCHAR_T_DEFINED)
    00387 __TBB_DECL_ATOMIC(wchar_t)
    00388 #endif /* _MSC_VER||!defined(_NATIVE_WCHAR_T_DEFINED) */
    00389
    00391 template<typename T> struct atomic<T*>: internal::atomic_impl_with_arithmetic<T*,ptrdiff_t,T> {
    00392     T* operator=( T* rhs ) {
    00393         // "this" required here in strict ISO C++ because store_with_release is a dependent name
    00394         return this->store_with_release(rhs);
    00395     }
    00396     atomic<T*>& operator=( const atomic<T*>& rhs ) {
    00397         this->store_with_release(rhs); return *this;
    00398     }
    00399     T* operator->() const {
    00400         return (*this);
    00401     }
    00402 };
    00403
    00405 template<> struct atomic<void*>: internal::atomic_impl<void*> {
    00406     void* operator=( void* rhs ) {
    00407         // "this" required here in strict ISO C++ because store_with_release is a dependent name
    00408         return this->store_with_release(rhs);
    00409     }
    00410     atomic<void*>& operator=( const atomic<void*>& rhs ) {
    00411         this->store_with_release(rhs); return *this;
    00412     }
    00413 };
    00414
    00415 // Helpers to workaround ugly syntax of calling template member function of a
    00416 // template class with template argument dependent on template parameters.
    00417
    00418 template <memory_semantics M, typename T>
    00419 T load ( const atomic<T>& a ) { return a.template load<M>(); }
    00420
    00421 template <memory_semantics M, typename T>
    00422 void store ( atomic<T>& a, T value ) { return a.template store<M>(value); }
    00423
    00424 namespace interface6{
    00426 template<typename T>
    00427 atomic<T> make_atomic(T t) {
    00428     atomic<T> a;
    00429     store<relaxed>(a,t);
    00430     return a;
    00431 }
    00432 }
    00433 using interface6::make_atomic;
    00434
    00435 namespace internal {
    00436
    00437 // only to aid in the gradual conversion of ordinary variables to proper atomics
    00438 template<typename T>
    00439 inline atomic<T>& as_atomic( T& t ) {
    00440     return (atomic<T>&)t;
    00441 }
    00442 } // namespace tbb::internal
    00443
    00444 } // namespace tbb
    00445
    00446 #if _MSC_VER && !__INTEL_COMPILER
    00447     #pragma warning (pop)
    00448 #endif // warnings 4244, 4267 are back
    00449
    00450 #endif /* __TBB_atomic_H */

Copyright © 2005-2012 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.