![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
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.