130 // prior value of *dest. xchg*() provide: |
130 // prior value of *dest. xchg*() provide: |
131 // <fence> exchange-value-with-dest <membar StoreLoad|StoreStore> |
131 // <fence> exchange-value-with-dest <membar StoreLoad|StoreStore> |
132 // The type T must be either a pointer type convertible to or equal |
132 // The type T must be either a pointer type convertible to or equal |
133 // to D, an integral/enum type equal to D, or a type equal to D that |
133 // to D, an integral/enum type equal to D, or a type equal to D that |
134 // is primitive convertible using PrimitiveConversions. |
134 // is primitive convertible using PrimitiveConversions. |
135 template<typename T, typename D> |
135 template<typename D, typename T> |
136 inline static D xchg(T exchange_value, volatile D* dest, |
136 inline static D xchg(volatile D* dest, T exchange_value, |
137 atomic_memory_order order = memory_order_conservative); |
137 atomic_memory_order order = memory_order_conservative); |
138 |
138 |
139 // Performs atomic compare of *dest and compare_value, and exchanges |
139 // Performs atomic compare of *dest and compare_value, and exchanges |
140 // *dest with exchange_value if the comparison succeeded. Returns prior |
140 // *dest with exchange_value if the comparison succeeded. Returns prior |
141 // value of *dest. cmpxchg*() provide: |
141 // value of *dest. cmpxchg*() provide: |
339 |
339 |
340 // Dispatch handler for xchg. Provides type-based validity |
340 // Dispatch handler for xchg. Provides type-based validity |
341 // checking and limited conversions around calls to the |
341 // checking and limited conversions around calls to the |
342 // platform-specific implementation layer provided by |
342 // platform-specific implementation layer provided by |
343 // PlatformXchg. |
343 // PlatformXchg. |
344 template<typename T, typename D, typename Enable = void> |
344 template<typename D, typename T, typename Enable = void> |
345 struct XchgImpl; |
345 struct XchgImpl; |
346 |
346 |
347 // Platform-specific implementation of xchg. Support for sizes |
347 // Platform-specific implementation of xchg. Support for sizes |
348 // of 4, and sizeof(intptr_t) are required. The class is a function |
348 // of 4, and sizeof(intptr_t) are required. The class is a function |
349 // object that must be default constructable, with these requirements: |
349 // object that must be default constructable, with these requirements: |
351 // - dest is of type T*. |
351 // - dest is of type T*. |
352 // - exchange_value is of type T. |
352 // - exchange_value is of type T. |
353 // - platform_xchg is an object of type PlatformXchg<sizeof(T)>. |
353 // - platform_xchg is an object of type PlatformXchg<sizeof(T)>. |
354 // |
354 // |
355 // Then |
355 // Then |
356 // platform_xchg(exchange_value, dest) |
356 // platform_xchg(dest, exchange_value) |
357 // must be a valid expression, returning a result convertible to T. |
357 // must be a valid expression, returning a result convertible to T. |
358 // |
358 // |
359 // A default definition is provided, which declares a function template |
359 // A default definition is provided, which declares a function template |
360 // T operator()(T, T volatile*, T, atomic_memory_order) const |
360 // T operator()(T volatile*, T, atomic_memory_order) const |
361 // |
361 // |
362 // For each required size, a platform must either provide an |
362 // For each required size, a platform must either provide an |
363 // appropriate definition of that function, or must entirely |
363 // appropriate definition of that function, or must entirely |
364 // specialize the class template for that size. |
364 // specialize the class template for that size. |
365 template<size_t byte_size> struct PlatformXchg; |
365 template<size_t byte_size> struct PlatformXchg; |
371 // helper invoked on the translated arguments, and the result |
371 // helper invoked on the translated arguments, and the result |
372 // translated back. Type is the parameter / return type of the |
372 // translated back. Type is the parameter / return type of the |
373 // helper function. |
373 // helper function. |
374 template<typename Type, typename Fn, typename T> |
374 template<typename Type, typename Fn, typename T> |
375 static T xchg_using_helper(Fn fn, |
375 static T xchg_using_helper(Fn fn, |
376 T exchange_value, |
376 T volatile* dest, |
377 T volatile* dest); |
377 T exchange_value); |
378 }; |
378 }; |
379 |
379 |
380 template<typename From, typename To> |
380 template<typename From, typename To> |
381 struct Atomic::IsPointerConvertible<From*, To*> : AllStatic { |
381 struct Atomic::IsPointerConvertible<From*, To*> : AllStatic { |
382 // Determine whether From* is implicitly convertible to To*, using |
382 // Determine whether From* is implicitly convertible to To*, using |
591 // specializations of the class. The platform file is responsible for |
591 // specializations of the class. The platform file is responsible for |
592 // providing those. |
592 // providing those. |
593 template<size_t byte_size> |
593 template<size_t byte_size> |
594 struct Atomic::PlatformXchg { |
594 struct Atomic::PlatformXchg { |
595 template<typename T> |
595 template<typename T> |
596 T operator()(T exchange_value, |
596 T operator()(T volatile* dest, |
597 T volatile* dest, |
597 T exchange_value, |
598 atomic_memory_order order) const; |
598 atomic_memory_order order) const; |
599 }; |
599 }; |
600 |
600 |
601 template <ScopedFenceType T> |
601 template <ScopedFenceType T> |
602 class ScopedFenceGeneral: public StackObj { |
602 class ScopedFenceGeneral: public StackObj { |
889 template<typename T> |
889 template<typename T> |
890 struct Atomic::XchgImpl< |
890 struct Atomic::XchgImpl< |
891 T, T, |
891 T, T, |
892 typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value>::type> |
892 typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value>::type> |
893 { |
893 { |
894 T operator()(T exchange_value, T volatile* dest, atomic_memory_order order) const { |
894 T operator()(T volatile* dest, T exchange_value, atomic_memory_order order) const { |
895 // Forward to the platform handler for the size of T. |
895 // Forward to the platform handler for the size of T. |
896 return PlatformXchg<sizeof(T)>()(exchange_value, dest, order); |
896 return PlatformXchg<sizeof(T)>()(dest, exchange_value, order); |
897 } |
897 } |
898 }; |
898 }; |
899 |
899 |
900 // Handle xchg for pointer types. |
900 // Handle xchg for pointer types. |
901 // |
901 // |
902 // The exchange_value must be implicitly convertible to the |
902 // The exchange_value must be implicitly convertible to the |
903 // destination's type; it must be type-correct to store the |
903 // destination's type; it must be type-correct to store the |
904 // exchange_value in the destination. |
904 // exchange_value in the destination. |
905 template<typename T, typename D> |
905 template<typename D, typename T> |
906 struct Atomic::XchgImpl< |
906 struct Atomic::XchgImpl< |
907 T*, D*, |
907 D*, T*, |
908 typename EnableIf<Atomic::IsPointerConvertible<T*, D*>::value>::type> |
908 typename EnableIf<Atomic::IsPointerConvertible<T*, D*>::value>::type> |
909 { |
909 { |
910 D* operator()(T* exchange_value, D* volatile* dest, atomic_memory_order order) const { |
910 D* operator()(D* volatile* dest, T* exchange_value, atomic_memory_order order) const { |
911 // Allow derived to base conversion, and adding cv-qualifiers. |
911 // Allow derived to base conversion, and adding cv-qualifiers. |
912 D* new_value = exchange_value; |
912 D* new_value = exchange_value; |
913 return PlatformXchg<sizeof(D*)>()(new_value, dest, order); |
913 return PlatformXchg<sizeof(D*)>()(dest, new_value, order); |
914 } |
914 } |
915 }; |
915 }; |
916 |
916 |
917 // Handle xchg for types that have a translator. |
917 // Handle xchg for types that have a translator. |
918 // |
918 // |
924 template<typename T> |
924 template<typename T> |
925 struct Atomic::XchgImpl< |
925 struct Atomic::XchgImpl< |
926 T, T, |
926 T, T, |
927 typename EnableIf<PrimitiveConversions::Translate<T>::value>::type> |
927 typename EnableIf<PrimitiveConversions::Translate<T>::value>::type> |
928 { |
928 { |
929 T operator()(T exchange_value, T volatile* dest, atomic_memory_order order) const { |
929 T operator()(T volatile* dest, T exchange_value, atomic_memory_order order) const { |
930 typedef PrimitiveConversions::Translate<T> Translator; |
930 typedef PrimitiveConversions::Translate<T> Translator; |
931 typedef typename Translator::Decayed Decayed; |
931 typedef typename Translator::Decayed Decayed; |
932 STATIC_ASSERT(sizeof(T) == sizeof(Decayed)); |
932 STATIC_ASSERT(sizeof(T) == sizeof(Decayed)); |
933 return Translator::recover( |
933 return Translator::recover( |
934 xchg(Translator::decay(exchange_value), |
934 xchg(reinterpret_cast<Decayed volatile*>(dest), |
935 reinterpret_cast<Decayed volatile*>(dest), |
935 Translator::decay(exchange_value), |
936 order)); |
936 order)); |
937 } |
937 } |
938 }; |
938 }; |
939 |
939 |
940 template<typename Type, typename Fn, typename T> |
940 template<typename Type, typename Fn, typename T> |
941 inline T Atomic::xchg_using_helper(Fn fn, |
941 inline T Atomic::xchg_using_helper(Fn fn, |
942 T exchange_value, |
942 T volatile* dest, |
943 T volatile* dest) { |
943 T exchange_value) { |
944 STATIC_ASSERT(sizeof(Type) == sizeof(T)); |
944 STATIC_ASSERT(sizeof(Type) == sizeof(T)); |
|
945 // Notice the swapped order of arguments. Change when/if stubs are rewritten. |
945 return PrimitiveConversions::cast<T>( |
946 return PrimitiveConversions::cast<T>( |
946 fn(PrimitiveConversions::cast<Type>(exchange_value), |
947 fn(PrimitiveConversions::cast<Type>(exchange_value), |
947 reinterpret_cast<Type volatile*>(dest))); |
948 reinterpret_cast<Type volatile*>(dest))); |
948 } |
949 } |
949 |
950 |
950 template<typename T, typename D> |
951 template<typename D, typename T> |
951 inline D Atomic::xchg(T exchange_value, volatile D* dest, atomic_memory_order order) { |
952 inline D Atomic::xchg(volatile D* dest, T exchange_value, atomic_memory_order order) { |
952 return XchgImpl<T, D>()(exchange_value, dest, order); |
953 return XchgImpl<D, T>()(dest, exchange_value, order); |
953 } |
954 } |
954 |
955 |
955 #endif // SHARE_RUNTIME_ATOMIC_HPP |
956 #endif // SHARE_RUNTIME_ATOMIC_HPP |