aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/base/atomic-utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/base/atomic-utils.h')
-rw-r--r--deps/v8/src/base/atomic-utils.h317
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>