X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=tbb%2Finclude%2Ftbb%2Fatomic.h;h=5257ff59ee07f9ae30d8f60d5e833a66d03ffeac;hb=4c96b4064a92f65beead3cb2453d727187bed40f;hp=d3600899f8a5c55177bc92727f89c8c8baf24a10;hpb=46ab0514ba58ee00183ff0584c7ea7c9e3d76494;p=casparcg diff --git a/tbb/include/tbb/atomic.h b/tbb/include/tbb/atomic.h index d3600899f..5257ff59e 100644 --- a/tbb/include/tbb/atomic.h +++ b/tbb/include/tbb/atomic.h @@ -50,24 +50,26 @@ namespace tbb { //! Specifies memory fencing. enum memory_semantics { - //! For internal use only. - __TBB_full_fence, + //! Sequentially consistent fence. + full_fence, //! Acquire fence acquire, //! Release fence - release + release, + //! No ordering + relaxed }; //! @cond INTERNAL namespace internal { -#if __GNUC__ || __SUNPRO_CC || __IBMCPP__ -#define __TBB_DECL_ATOMIC_FIELD(t,f,a) t f __attribute__ ((aligned(a))); -#elif defined(__INTEL_COMPILER)||_MSC_VER >= 1300 -#define __TBB_DECL_ATOMIC_FIELD(t,f,a) __declspec(align(a)) t f; +#if __TBB_ATTRIBUTE_ALIGNED_PRESENT + #define __TBB_DECL_ATOMIC_FIELD(t,f,a) t f __attribute__ ((aligned(a))); +#elif __TBB_DECLSPEC_ALIGN_PRESENT + #define __TBB_DECL_ATOMIC_FIELD(t,f,a) __declspec(align(a)) t f; #else -#error Do not know syntax for forcing alignment. -#endif /* __GNUC__ */ + #error Do not know syntax for forcing alignment. +#endif template struct atomic_rep; // Primary template declared, but never defined. @@ -103,58 +105,82 @@ struct atomic_rep<8> { // Specialization template struct atomic_traits; // Primary template declared, but not defined. -#define __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(S,M) \ - template<> struct atomic_traits { \ - typedef atomic_rep::word word; \ - inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) {\ - return __TBB_CompareAndSwap##S##M(location,new_value,comparand); \ - } \ - inline static word fetch_and_add( volatile void* location, word addend ) { \ - return __TBB_FetchAndAdd##S##M(location,addend); \ - } \ - inline static word fetch_and_store( volatile void* location, word value ) {\ - return __TBB_FetchAndStore##S##M(location,value); \ - } \ +#define __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(S,M) \ + template<> struct atomic_traits { \ + typedef atomic_rep::word word; \ + inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \ + return __TBB_machine_cmpswp##S##M(location,new_value,comparand); \ + } \ + inline static word fetch_and_add( volatile void* location, word addend ) { \ + return __TBB_machine_fetchadd##S##M(location,addend); \ + } \ + inline static word fetch_and_store( volatile void* location, word value ) { \ + return __TBB_machine_fetchstore##S##M(location,value); \ + } \ }; -#define __TBB_DECL_ATOMIC_PRIMITIVES(S) \ - template \ - struct atomic_traits { \ - typedef atomic_rep::word word; \ - inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) {\ - return __TBB_CompareAndSwap##S(location,new_value,comparand); \ - } \ - inline static word fetch_and_add( volatile void* location, word addend ) { \ - return __TBB_FetchAndAdd##S(location,addend); \ - } \ - inline static word fetch_and_store( volatile void* location, word value ) {\ - return __TBB_FetchAndStore##S(location,value); \ - } \ +#define __TBB_DECL_ATOMIC_PRIMITIVES(S) \ + template \ + struct atomic_traits { \ + typedef atomic_rep::word word; \ + inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \ + return __TBB_machine_cmpswp##S(location,new_value,comparand); \ + } \ + inline static word fetch_and_add( volatile void* location, word addend ) { \ + return __TBB_machine_fetchadd##S(location,addend); \ + } \ + inline static word fetch_and_store( volatile void* location, word value ) { \ + return __TBB_machine_fetchstore##S(location,value); \ + } \ }; -#if __TBB_DECL_FENCED_ATOMICS -__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,__TBB_full_fence) -__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,__TBB_full_fence) -__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,__TBB_full_fence) -__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,__TBB_full_fence) +template +struct atomic_load_store_traits; // Primary template declaration + +#define __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(M) \ + template<> struct atomic_load_store_traits { \ + template \ + inline static T load( const volatile T& location ) { \ + return __TBB_load_##M( location ); \ + } \ + template \ + inline static void store( volatile T& location, T value ) { \ + __TBB_store_##M( location, value ); \ + } \ + } + +#if __TBB_USE_FENCED_ATOMICS +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,full_fence) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,full_fence) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,full_fence) __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,acquire) __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,acquire) __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,acquire) __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,release) __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,release) __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,release) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,relaxed) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,relaxed) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,relaxed) #if __TBB_64BIT_ATOMICS +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,full_fence) __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,acquire) __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,release) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,relaxed) #endif -#else +#else /* !__TBB_USE_FENCED_ATOMICS */ __TBB_DECL_ATOMIC_PRIMITIVES(1) __TBB_DECL_ATOMIC_PRIMITIVES(2) __TBB_DECL_ATOMIC_PRIMITIVES(4) #if __TBB_64BIT_ATOMICS __TBB_DECL_ATOMIC_PRIMITIVES(8) #endif -#endif +#endif /* !__TBB_USE_FENCED_ATOMICS */ + +__TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(full_fence); +__TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(acquire); +__TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(release); +__TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(relaxed); //! Additive inverse of 1 for type T. /** Various compilers issue various warnings if -1 is used with various integer types. @@ -186,7 +212,7 @@ public: } value_type fetch_and_store( value_type value ) { - return fetch_and_store<__TBB_full_fence>(value); + return fetch_and_store(value); } template @@ -199,7 +225,7 @@ public: } value_type compare_and_swap( value_type value, value_type comparand ) { - return compare_and_swap<__TBB_full_fence>(value,comparand); + return compare_and_swap(value,comparand); } operator value_type() const volatile { // volatile qualifier here for backwards compatibility @@ -208,6 +234,28 @@ public: return w.value; } + template + value_type load () const { + converter u; + u.bits = internal::atomic_load_store_traits::load( rep.value ); + return u.value; + } + + value_type load () const { + return load(); + } + + template + void store ( value_type value ) { + converter u; + u.value = value; + internal::atomic_load_store_traits::store( rep.value, u.bits ); + } + + void store ( value_type value ) { + store( value ); + } + protected: value_type store_with_release( value_type rhs ) { converter u; @@ -232,7 +280,7 @@ public: } value_type fetch_and_add( D addend ) { - return fetch_and_add<__TBB_full_fence>(addend); + return fetch_and_add(addend); } template @@ -303,9 +351,10 @@ struct atomic: internal::atomic_impl { }; #if __TBB_64BIT_ATOMICS -// otherwise size is verified by test_atomic __TBB_DECL_ATOMIC(__TBB_LONG_LONG) __TBB_DECL_ATOMIC(unsigned __TBB_LONG_LONG) +#else +// test_atomic will verify that sizeof(long long)==8 #endif __TBB_DECL_ATOMIC(long) __TBB_DECL_ATOMIC(unsigned long) @@ -363,6 +412,15 @@ template<> struct atomic: internal::atomic_impl { } }; +// Helpers to workaround ugly syntax of calling template member function of a +// template class with template argument dependent on template parameters. + +template +T load ( const atomic& a ) { return a.template load(); } + +template +void store ( atomic& a, T value ) { return a.template store(value); } + } // namespace tbb #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)