summaryrefslogtreecommitdiff
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.h173
1 files changed, 170 insertions, 3 deletions
diff --git a/deps/v8/src/base/atomic-utils.h b/deps/v8/src/base/atomic-utils.h
index f4f43fc817..a7f5b3ca8e 100644
--- a/deps/v8/src/base/atomic-utils.h
+++ b/deps/v8/src/base/atomic-utils.h
@@ -6,6 +6,7 @@
#define V8_ATOMIC_UTILS_H_
#include <limits.h>
+#include <type_traits>
#include "src/base/atomicops.h"
#include "src/base/macros.h"
@@ -68,18 +69,18 @@ class NoBarrierAtomicValue {
}
V8_INLINE bool TrySetValue(T old_value, T new_value) {
- return base::NoBarrier_CompareAndSwap(
+ return base::Relaxed_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 T Value() const {
- return cast_helper<T>::to_return_type(base::NoBarrier_Load(&value_));
+ return cast_helper<T>::to_return_type(base::Relaxed_Load(&value_));
}
V8_INLINE void SetValue(T new_value) {
- base::NoBarrier_Store(&value_, cast_helper<T>::to_storage_type(new_value));
+ base::Relaxed_Store(&value_, cast_helper<T>::to_storage_type(new_value));
}
private:
@@ -250,6 +251,172 @@ class AtomicEnumSet {
base::AtomicWord bits_;
};
+class AsAtomic32 {
+ 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)));
+ }
+
+ 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)));
+ }
+
+ 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));
+ }
+
+ 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);
+ }
+};
+
+// 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) {
+ AsAtomicWord::Relaxed_Store(&value_,
+ AsAtomicWord::Relaxed_Load(&other.value_));
+ }
+
+ void operator=(const AtomicElement<T>& other) {
+ AsAtomicWord::Relaxed_Store(&value_,
+ AsAtomicWord::Relaxed_Load(&other.value_));
+ }
+
+ T value() const { return AsAtomicWord::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_;
+};
+
} // namespace base
} // namespace v8