Shadowrun: Awakened 29 September 2011 - Build 871
atomic.h
Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2010 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 <cstddef>
00033 #include "tbb_stddef.h"
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     __TBB_full_fence,
00056     acquire,
00058     release
00059 };
00060 
00062 namespace internal {
00063 
00064 #if __GNUC__ || __SUNPRO_CC
00065 #define __TBB_DECL_ATOMIC_FIELD(t,f,a) t f  __attribute__ ((aligned(a)));
00066 #elif defined(__INTEL_COMPILER)||_MSC_VER >= 1300
00067 #define __TBB_DECL_ATOMIC_FIELD(t,f,a) __declspec(align(a)) t f;
00068 #else 
00069 #error Do not know syntax for forcing alignment.
00070 #endif /* __GNUC__ */
00071 
00072 template<size_t S>
00073 struct atomic_rep;           // Primary template declared, but never defined.
00074 
00075 template<>
00076 struct atomic_rep<1> {       // Specialization
00077     typedef int8_t word;
00078     int8_t value;
00079 };
00080 template<>
00081 struct atomic_rep<2> {       // Specialization
00082     typedef int16_t word;
00083     __TBB_DECL_ATOMIC_FIELD(int16_t,value,2)
00084 };
00085 template<>
00086 struct atomic_rep<4> {       // Specialization
00087 #if _MSC_VER && __TBB_WORDSIZE==4
00088     // Work-around that avoids spurious /Wp64 warnings
00089     typedef intptr_t word;
00090 #else
00091     typedef int32_t word;
00092 #endif
00093     __TBB_DECL_ATOMIC_FIELD(int32_t,value,4)
00094 };
00095 template<>
00096 struct atomic_rep<8> {       // Specialization
00097     typedef int64_t word;
00098     __TBB_DECL_ATOMIC_FIELD(int64_t,value,8)
00099 };
00100 
00101 template<size_t Size, memory_semantics M>
00102 struct atomic_traits;        // Primary template declared, but not defined.
00103 
00104 #define __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(S,M)                         \
00105     template<> struct atomic_traits<S,M> {                               \
00106         typedef atomic_rep<S>::word word;                               \
00107         inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) {\
00108             return __TBB_CompareAndSwap##S##M(location,new_value,comparand);    \
00109         }                                                                       \
00110         inline static word fetch_and_add( volatile void* location, word addend ) { \
00111             return __TBB_FetchAndAdd##S##M(location,addend);                    \
00112         }                                                                       \
00113         inline static word fetch_and_store( volatile void* location, word value ) {\
00114             return __TBB_FetchAndStore##S##M(location,value);                   \
00115         }                                                                       \
00116     };
00117 
00118 #define __TBB_DECL_ATOMIC_PRIMITIVES(S)                                  \
00119     template<memory_semantics M>                                         \
00120     struct atomic_traits<S,M> {                                          \
00121         typedef atomic_rep<S>::word word;                               \
00122         inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) {\
00123             return __TBB_CompareAndSwap##S(location,new_value,comparand);       \
00124         }                                                                       \
00125         inline static word fetch_and_add( volatile void* location, word addend ) { \
00126             return __TBB_FetchAndAdd##S(location,addend);                       \
00127         }                                                                       \
00128         inline static word fetch_and_store( volatile void* location, word value ) {\
00129             return __TBB_FetchAndStore##S(location,value);                      \
00130         }                                                                       \
00131     };
00132 
00133 #if __TBB_DECL_FENCED_ATOMICS
00134 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,__TBB_full_fence)
00135 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,__TBB_full_fence)
00136 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,__TBB_full_fence)
00137 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,__TBB_full_fence)
00138 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,acquire)
00139 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,acquire)
00140 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,acquire)
00141 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,acquire)
00142 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,release)
00143 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,release)
00144 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,release)
00145 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,release)
00146 #else
00147 __TBB_DECL_ATOMIC_PRIMITIVES(1)
00148 __TBB_DECL_ATOMIC_PRIMITIVES(2)
00149 __TBB_DECL_ATOMIC_PRIMITIVES(4)
00150 __TBB_DECL_ATOMIC_PRIMITIVES(8)
00151 #endif
00152 
00154 
00156 #define __TBB_MINUS_ONE(T) (T(T(0)-T(1)))
00157 
00159 
00161 template<typename T>
00162 struct atomic_impl {
00163 protected:
00164     atomic_rep<sizeof(T)> rep;
00165 private:
00167     union converter {
00168         T value;
00169         typename atomic_rep<sizeof(T)>::word bits;
00170     };
00171 public:
00172     typedef T value_type;
00173 
00174     template<memory_semantics M>
00175     value_type fetch_and_store( value_type value ) {
00176         converter u, w;
00177         u.value = value;
00178         w.bits = internal::atomic_traits<sizeof(value_type),M>::fetch_and_store(&rep.value,u.bits);
00179         return w.value;
00180     }
00181 
00182     value_type fetch_and_store( value_type value ) {
00183         return fetch_and_store<__TBB_full_fence>(value);
00184     }
00185 
00186     template<memory_semantics M>
00187     value_type compare_and_swap( value_type value, value_type comparand ) {
00188         converter u, v, w;
00189         u.value = value;
00190         v.value = comparand;
00191         w.bits = internal::atomic_traits<sizeof(value_type),M>::compare_and_swap(&rep.value,u.bits,v.bits);
00192         return w.value;
00193     }
00194 
00195     value_type compare_and_swap( value_type value, value_type comparand ) {
00196         return compare_and_swap<__TBB_full_fence>(value,comparand);
00197     }
00198 
00199     operator value_type() const volatile {                // volatile qualifier here for backwards compatibility 
00200         converter w;
00201         w.bits = __TBB_load_with_acquire( rep.value );
00202         return w.value;
00203     }
00204 
00205 protected:
00206     value_type store_with_release( value_type rhs ) {
00207         converter u;
00208         u.value = rhs;
00209         __TBB_store_with_release(rep.value,u.bits);
00210         return rhs;
00211     }
00212 };
00213 
00215 
00218 template<typename I, typename D, typename StepType>
00219 struct atomic_impl_with_arithmetic: atomic_impl<I> {
00220 public:
00221     typedef I value_type;
00222 
00223     template<memory_semantics M>
00224     value_type fetch_and_add( D addend ) {
00225         return value_type(internal::atomic_traits<sizeof(value_type),M>::fetch_and_add( &this->rep.value, addend*sizeof(StepType) ));
00226     }
00227 
00228     value_type fetch_and_add( D addend ) {
00229         return fetch_and_add<__TBB_full_fence>(addend);
00230     }
00231 
00232     template<memory_semantics M>
00233     value_type fetch_and_increment() {
00234         return fetch_and_add<M>(1);
00235     }
00236 
00237     value_type fetch_and_increment() {
00238         return fetch_and_add(1);
00239     }
00240 
00241     template<memory_semantics M>
00242     value_type fetch_and_decrement() {
00243         return fetch_and_add<M>(__TBB_MINUS_ONE(D));
00244     }
00245 
00246     value_type fetch_and_decrement() {
00247         return fetch_and_add(__TBB_MINUS_ONE(D));
00248     }
00249 
00250 public:
00251     value_type operator+=( D addend ) {
00252         return fetch_and_add(addend)+addend;
00253     }
00254 
00255     value_type operator-=( D addend ) {
00256         // Additive inverse of addend computed using binary minus,
00257         // instead of unary minus, for sake of avoiding compiler warnings.
00258         return operator+=(D(0)-addend);    
00259     }
00260 
00261     value_type operator++() {
00262         return fetch_and_add(1)+1;
00263     }
00264 
00265     value_type operator--() {
00266         return fetch_and_add(__TBB_MINUS_ONE(D))-1;
00267     }
00268 
00269     value_type operator++(int) {
00270         return fetch_and_add(1);
00271     }
00272 
00273     value_type operator--(int) {
00274         return fetch_and_add(__TBB_MINUS_ONE(D));
00275     }
00276 };
00277 
00278 #if __TBB_WORDSIZE == 4
00279 // Plaforms with 32-bit hardware require special effort for 64-bit loads and stores.
00280 #if defined(__INTEL_COMPILER)||!defined(_MSC_VER)||_MSC_VER>=1400
00281 
00282 template<>
00283 inline atomic_impl<__TBB_LONG_LONG>::operator atomic_impl<__TBB_LONG_LONG>::value_type() const volatile {
00284     return __TBB_Load8(&rep.value);
00285 }
00286 
00287 template<>
00288 inline atomic_impl<unsigned __TBB_LONG_LONG>::operator atomic_impl<unsigned __TBB_LONG_LONG>::value_type() const volatile {
00289     return __TBB_Load8(&rep.value);
00290 }
00291 
00292 template<>
00293 inline atomic_impl<__TBB_LONG_LONG>::value_type atomic_impl<__TBB_LONG_LONG>::store_with_release( value_type rhs ) {
00294     __TBB_Store8(&rep.value,rhs);
00295     return rhs;
00296 }
00297 
00298 template<>
00299 inline atomic_impl<unsigned __TBB_LONG_LONG>::value_type atomic_impl<unsigned __TBB_LONG_LONG>::store_with_release( value_type rhs ) {
00300     __TBB_Store8(&rep.value,rhs);
00301     return rhs;
00302 }
00303 
00304 #endif /* defined(__INTEL_COMPILER)||!defined(_MSC_VER)||_MSC_VER>=1400 */
00305 #endif /* __TBB_WORDSIZE==4 */
00306 
00307 } /* Internal */
00309 
00311 
00313 template<typename T>
00314 struct atomic: internal::atomic_impl<T> {
00315     T operator=( T rhs ) {
00316         // "this" required here in strict ISO C++ because store_with_release is a dependent name
00317         return this->store_with_release(rhs);
00318     }
00319     atomic<T>& operator=( const atomic<T>& rhs ) {this->store_with_release(rhs); return *this;}
00320 };
00321 
00322 #define __TBB_DECL_ATOMIC(T) \
00323     template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {  \
00324         T operator=( T rhs ) {return store_with_release(rhs);}  \
00325         atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}  \
00326     };
00327 
00328 #if defined(__INTEL_COMPILER)||!defined(_MSC_VER)||_MSC_VER>=1400
00329 __TBB_DECL_ATOMIC(__TBB_LONG_LONG)
00330 __TBB_DECL_ATOMIC(unsigned __TBB_LONG_LONG)
00331 #else
00332 // Some old versions of MVSC cannot correctly compile templates with "long long".
00333 #endif /* defined(__INTEL_COMPILER)||!defined(_MSC_VER)||_MSC_VER>=1400 */
00334 
00335 __TBB_DECL_ATOMIC(long)
00336 __TBB_DECL_ATOMIC(unsigned long)
00337 
00338 #if defined(_MSC_VER) && __TBB_WORDSIZE==4
00339 /* Special version of __TBB_DECL_ATOMIC that avoids gratuitous warnings from cl /Wp64 option. 
00340    It is identical to __TBB_DECL_ATOMIC(unsigned) except that it replaces operator=(T) 
00341    with an operator=(U) that explicitly converts the U to a T.  Types T and U should be
00342    type synonyms on the platform.  Type U should be the wider variant of T from the
00343    perspective of /Wp64. */
00344 #define __TBB_DECL_ATOMIC_ALT(T,U) \
00345     template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {  \
00346         T operator=( U rhs ) {return store_with_release(T(rhs));}  \
00347         atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}  \
00348     };
00349 __TBB_DECL_ATOMIC_ALT(unsigned,size_t)
00350 __TBB_DECL_ATOMIC_ALT(int,ptrdiff_t)
00351 #else
00352 __TBB_DECL_ATOMIC(unsigned)
00353 __TBB_DECL_ATOMIC(int)
00354 #endif /* defined(_MSC_VER) && __TBB_WORDSIZE==4 */
00355 
00356 __TBB_DECL_ATOMIC(unsigned short)
00357 __TBB_DECL_ATOMIC(short)
00358 __TBB_DECL_ATOMIC(char)
00359 __TBB_DECL_ATOMIC(signed char)
00360 __TBB_DECL_ATOMIC(unsigned char)
00361 
00362 #if !defined(_MSC_VER)||defined(_NATIVE_WCHAR_T_DEFINED) 
00363 __TBB_DECL_ATOMIC(wchar_t)
00364 #endif /* _MSC_VER||!defined(_NATIVE_WCHAR_T_DEFINED) */
00365 
00367 template<typename T> struct atomic<T*>: internal::atomic_impl_with_arithmetic<T*,ptrdiff_t,T> {
00368     T* operator=( T* rhs ) {
00369         // "this" required here in strict ISO C++ because store_with_release is a dependent name
00370         return this->store_with_release(rhs);
00371     }
00372     atomic<T*>& operator=( const atomic<T*>& rhs ) {
00373         this->store_with_release(rhs); return *this;
00374     }
00375     T* operator->() const {
00376         return (*this);
00377     }
00378 };
00379 
00381 template<> struct atomic<void*>: internal::atomic_impl<void*> {
00382     void* operator=( void* rhs ) {
00383         // "this" required here in strict ISO C++ because store_with_release is a dependent name
00384         return this->store_with_release(rhs);
00385     }
00386     atomic<void*>& operator=( const atomic<void*>& rhs ) {
00387         this->store_with_release(rhs); return *this;
00388     }
00389 };
00390 
00391 } // namespace tbb
00392 
00393 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
00394     #pragma warning (pop)
00395 #endif // warnings 4244, 4267 are back
00396 
00397 #endif /* __TBB_atomic_H */

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net