diff options
Diffstat (limited to 'deps/v8/src/base/atomic-utils.h')
-rw-r--r-- | deps/v8/src/base/atomic-utils.h | 317 |
1 files changed, 53 insertions, 264 deletions
diff --git a/deps/v8/src/base/atomic-utils.h b/deps/v8/src/base/atomic-utils.h index 90681b8a35..2c6fd23b71 100644 --- a/deps/v8/src/base/atomic-utils.h +++ b/deps/v8/src/base/atomic-utils.h @@ -28,29 +28,6 @@ class AtomicValue { return cast_helper<T>::to_return_type(base::Acquire_Load(&value_)); } - V8_INLINE bool TrySetValue(T old_value, T new_value) { - return base::Release_CompareAndSwap( - &value_, cast_helper<T>::to_storage_type(old_value), - cast_helper<T>::to_storage_type(new_value)) == - cast_helper<T>::to_storage_type(old_value); - } - - V8_INLINE void SetBits(T bits, T mask) { - DCHECK_EQ(bits & ~mask, static_cast<T>(0)); - T old_value; - T new_value; - do { - old_value = Value(); - new_value = (old_value & ~mask) | bits; - } while (!TrySetValue(old_value, new_value)); - } - - V8_INLINE void SetBit(int bit) { - SetBits(static_cast<T>(1) << bit, static_cast<T>(1) << bit); - } - - V8_INLINE void ClearBit(int bit) { SetBits(0, 1 << bit); } - V8_INLINE void SetValue(T new_value) { base::Release_Store(&value_, cast_helper<T>::to_storage_type(new_value)); } @@ -81,122 +58,57 @@ class AtomicValue { base::AtomicWord value_; }; -class AsAtomic32 { +// Provides atomic operations for a values stored at some address. +template <typename TAtomicStorageType> +class AsAtomicImpl { public: - template <typename T> - static T Acquire_Load(T* addr) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic32)); - return to_return_type<T>(base::Acquire_Load(to_storage_addr(addr))); - } + using AtomicStorageType = TAtomicStorageType; template <typename T> - static T Relaxed_Load(T* addr) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic32)); - return to_return_type<T>(base::Relaxed_Load(to_storage_addr(addr))); - } - - template <typename T> - static void Release_Store(T* addr, - typename std::remove_reference<T>::type new_value) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic32)); - base::Release_Store(to_storage_addr(addr), to_storage_type(new_value)); - } - - template <typename T> - static void Relaxed_Store(T* addr, - typename std::remove_reference<T>::type new_value) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic32)); - base::Relaxed_Store(to_storage_addr(addr), to_storage_type(new_value)); - } - - template <typename T> - static T Release_CompareAndSwap( - T* addr, typename std::remove_reference<T>::type old_value, - typename std::remove_reference<T>::type new_value) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic32)); - return to_return_type<T>(base::Release_CompareAndSwap( - to_storage_addr(addr), to_storage_type(old_value), - to_storage_type(new_value))); - } - - // Atomically sets bits selected by the mask to the given value. - // Returns false if the bits are already set as needed. - template <typename T> - static bool SetBits(T* addr, T bits, T mask) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic32)); - DCHECK_EQ(bits & ~mask, static_cast<T>(0)); - T old_value; - T new_value; - do { - old_value = Relaxed_Load(addr); - if ((old_value & mask) == bits) return false; - new_value = (old_value & ~mask) | bits; - } while (Release_CompareAndSwap(addr, old_value, new_value) != old_value); - return true; - } - - private: - template <typename T> - static base::Atomic32 to_storage_type(T value) { - return static_cast<base::Atomic32>(value); - } - template <typename T> - static T to_return_type(base::Atomic32 value) { - return static_cast<T>(value); - } - template <typename T> - static base::Atomic32* to_storage_addr(T* value) { - return reinterpret_cast<base::Atomic32*>(value); - } - template <typename T> - static const base::Atomic32* to_storage_addr(const T* value) { - return reinterpret_cast<const base::Atomic32*>(value); - } -}; - -class AsAtomicWord { - public: - template <typename T> static T Acquire_Load(T* addr) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); - return to_return_type<T>(base::Acquire_Load(to_storage_addr(addr))); + STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType)); + return cast_helper<T>::to_return_type( + base::Acquire_Load(to_storage_addr(addr))); } template <typename T> static T Relaxed_Load(T* addr) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); - return to_return_type<T>(base::Relaxed_Load(to_storage_addr(addr))); + STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType)); + return cast_helper<T>::to_return_type( + base::Relaxed_Load(to_storage_addr(addr))); } template <typename T> static void Release_Store(T* addr, typename std::remove_reference<T>::type new_value) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); - base::Release_Store(to_storage_addr(addr), to_storage_type(new_value)); + STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType)); + base::Release_Store(to_storage_addr(addr), + cast_helper<T>::to_storage_type(new_value)); } template <typename T> static void Relaxed_Store(T* addr, typename std::remove_reference<T>::type new_value) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); - base::Relaxed_Store(to_storage_addr(addr), to_storage_type(new_value)); + STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType)); + base::Relaxed_Store(to_storage_addr(addr), + cast_helper<T>::to_storage_type(new_value)); } template <typename T> static T Release_CompareAndSwap( T* addr, typename std::remove_reference<T>::type old_value, typename std::remove_reference<T>::type new_value) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); - return to_return_type<T>(base::Release_CompareAndSwap( - to_storage_addr(addr), to_storage_type(old_value), - to_storage_type(new_value))); + STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType)); + return cast_helper<T>::to_return_type(base::Release_CompareAndSwap( + to_storage_addr(addr), cast_helper<T>::to_storage_type(old_value), + cast_helper<T>::to_storage_type(new_value))); } // Atomically sets bits selected by the mask to the given value. // Returns false if the bits are already set as needed. template <typename T> static bool SetBits(T* addr, T bits, T mask) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); + STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType)); DCHECK_EQ(bits & ~mask, static_cast<T>(0)); T old_value; T new_value; @@ -209,173 +121,50 @@ class AsAtomicWord { } private: - template <typename T> - static base::AtomicWord to_storage_type(T value) { - return static_cast<base::AtomicWord>(value); - } - template <typename T> - static T to_return_type(base::AtomicWord value) { - return static_cast<T>(value); - } - template <typename T> - static base::AtomicWord* to_storage_addr(T* value) { - return reinterpret_cast<base::AtomicWord*>(value); - } - template <typename T> - static const base::AtomicWord* to_storage_addr(const T* value) { - return reinterpret_cast<const base::AtomicWord*>(value); - } -}; - -class AsAtomic8 { - public: - template <typename T> - static T Acquire_Load(T* addr) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic8)); - return to_return_type<T>(base::Acquire_Load(to_storage_addr(addr))); - } - - template <typename T> - static T Relaxed_Load(T* addr) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic8)); - return to_return_type<T>(base::Relaxed_Load(to_storage_addr(addr))); - } - - template <typename T> - static void Release_Store(T* addr, - typename std::remove_reference<T>::type new_value) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic8)); - base::Release_Store(to_storage_addr(addr), to_storage_type(new_value)); - } - - template <typename T> - static void Relaxed_Store(T* addr, - typename std::remove_reference<T>::type new_value) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic8)); - base::Relaxed_Store(to_storage_addr(addr), to_storage_type(new_value)); - } + template <typename U> + struct cast_helper { + static AtomicStorageType to_storage_type(U value) { + return static_cast<AtomicStorageType>(value); + } + static U to_return_type(AtomicStorageType value) { + return static_cast<U>(value); + } + }; - template <typename T> - static T Release_CompareAndSwap( - T* addr, typename std::remove_reference<T>::type old_value, - typename std::remove_reference<T>::type new_value) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic8)); - return to_return_type<T>(base::Release_CompareAndSwap( - to_storage_addr(addr), to_storage_type(old_value), - to_storage_type(new_value))); - } + template <typename U> + struct cast_helper<U*> { + static AtomicStorageType to_storage_type(U* value) { + return reinterpret_cast<AtomicStorageType>(value); + } + static U* to_return_type(AtomicStorageType value) { + return reinterpret_cast<U*>(value); + } + }; - private: template <typename T> - static base::Atomic8 to_storage_type(T value) { - return static_cast<base::Atomic8>(value); + static AtomicStorageType* to_storage_addr(T* value) { + return reinterpret_cast<AtomicStorageType*>(value); } template <typename T> - static T to_return_type(base::Atomic8 value) { - return static_cast<T>(value); - } - template <typename T> - static base::Atomic8* to_storage_addr(T* value) { - return reinterpret_cast<base::Atomic8*>(value); - } - template <typename T> - static const base::Atomic8* to_storage_addr(const T* value) { - return reinterpret_cast<const base::Atomic8*>(value); + static const AtomicStorageType* to_storage_addr(const T* value) { + return reinterpret_cast<const AtomicStorageType*>(value); } }; -class AsAtomicPointer { - public: - template <typename T> - static T Acquire_Load(T* addr) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); - return to_return_type<T>(base::Acquire_Load(to_storage_addr(addr))); - } - - template <typename T> - static T Relaxed_Load(T* addr) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); - return to_return_type<T>(base::Relaxed_Load(to_storage_addr(addr))); - } - - template <typename T> - static void Release_Store(T* addr, - typename std::remove_reference<T>::type new_value) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); - base::Release_Store(to_storage_addr(addr), to_storage_type(new_value)); - } - - template <typename T> - static void Relaxed_Store(T* addr, - typename std::remove_reference<T>::type new_value) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); - base::Relaxed_Store(to_storage_addr(addr), to_storage_type(new_value)); - } +using AsAtomic8 = AsAtomicImpl<base::Atomic8>; +using AsAtomic32 = AsAtomicImpl<base::Atomic32>; +using AsAtomicWord = AsAtomicImpl<base::AtomicWord>; +// This is similar to AsAtomicWord but it explicitly deletes functionality +// provided atomic access to bit representation of stored values. +template <typename TAtomicStorageType> +class AsAtomicPointerImpl : public AsAtomicImpl<TAtomicStorageType> { + public: template <typename T> - static T Release_CompareAndSwap( - T* addr, typename std::remove_reference<T>::type old_value, - typename std::remove_reference<T>::type new_value) { - STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); - return to_return_type<T>(base::Release_CompareAndSwap( - to_storage_addr(addr), to_storage_type(old_value), - to_storage_type(new_value))); - } - - private: - template <typename T> - static base::AtomicWord to_storage_type(T value) { - return reinterpret_cast<base::AtomicWord>(value); - } - template <typename T> - static T to_return_type(base::AtomicWord value) { - return reinterpret_cast<T>(value); - } - template <typename T> - static base::AtomicWord* to_storage_addr(T* value) { - return reinterpret_cast<base::AtomicWord*>(value); - } - template <typename T> - static const base::AtomicWord* to_storage_addr(const T* value) { - return reinterpret_cast<const base::AtomicWord*>(value); - } + static bool SetBits(T* addr, T bits, T mask) = delete; }; -// This class is intended to be used as a wrapper for elements of an array -// that is passed in to STL functions such as std::sort. It ensures that -// elements accesses are atomic. -// Usage example: -// Object** given_array; -// AtomicElement<Object*>* wrapped = -// reinterpret_cast<AtomicElement<Object*>(given_array); -// std::sort(wrapped, wrapped + given_length, cmp); -// where the cmp function uses the value() accessor to compare the elements. -template <typename T> -class AtomicElement { - public: - AtomicElement(const AtomicElement<T>& other) { - AsAtomicPointer::Relaxed_Store( - &value_, AsAtomicPointer::Relaxed_Load(&other.value_)); - } - - void operator=(const AtomicElement<T>& other) { - AsAtomicPointer::Relaxed_Store( - &value_, AsAtomicPointer::Relaxed_Load(&other.value_)); - } - - T value() const { return AsAtomicPointer::Relaxed_Load(&value_); } - - bool operator<(const AtomicElement<T>& other) const { - return value() < other.value(); - } - - bool operator==(const AtomicElement<T>& other) const { - return value() == other.value(); - } - - private: - T value_; -}; +using AsAtomicPointer = AsAtomicPointerImpl<base::AtomicWord>; template <typename T, typename = typename std::enable_if<std::is_unsigned<T>::value>::type> |