Index: src/atomic-utils.h |
diff --git a/src/atomic-utils.h b/src/atomic-utils.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..cbdee04fc83c92151a17bb0575061d0ac6dd3cb6 |
--- /dev/null |
+++ b/src/atomic-utils.h |
@@ -0,0 +1,135 @@ |
+// Copyright 2015 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef V8_ATOMIC_UTILS_H_ |
+#define V8_ATOMIC_UTILS_H_ |
+ |
+#include <limits.h> |
+ |
+#include "src/base/atomicops.h" |
+#include "src/base/macros.h" |
+ |
+namespace v8 { |
+namespace internal { |
+ |
+class AtomicValue { |
+ public: |
+ AtomicValue() : value_(0) {} |
+ explicit AtomicValue(base::AtomicWord initial) : value_(initial) {} |
+ |
+ V8_INLINE void Increment(base::AtomicWord increment) { |
+ base::NoBarrier_AtomicIncrement(&value_, increment); |
+ } |
+ |
+ V8_INLINE base::AtomicWord Value() { return base::NoBarrier_Load(&value_); } |
+ |
+ V8_INLINE void SetValue(base::AtomicWord new_value) { |
+ base::NoBarrier_Store(&value_, new_value); |
+ } |
+ |
+ private: |
+ base::AtomicWord value_; |
+}; |
+ |
+ |
+// See utils.h for EnumSet. Storage is always base::AtomicWord. |
+// Requirements on E: |
+// - No explicit values. |
+// - E::kLastValue defined to be the last actually used value. |
+// |
+// Example: |
+// enum E { kA, kB, kC, kLastValue = kC }; |
+template <class E> |
+class AtomicEnumSet { |
+ public: |
+ explicit AtomicEnumSet(base::AtomicWord bits = 0) : bits_(bits) {} |
+ |
+ bool IsEmpty() const { return ToIntegral() == 0; } |
+ |
+ bool Contains(E element) const { return (ToIntegral() & Mask(element)) != 0; } |
+ |
+ bool ContainsAnyOf(const AtomicEnumSet& set) const { |
+ return (ToIntegral() & set.ToIntegral()) != 0; |
+ } |
+ |
+ void RemoveAll() { base::NoBarrier_Store(&bits_, 0); } |
+ |
+ bool operator==(const AtomicEnumSet& set) const { |
+ return ToIntegral() == set.ToIntegral(); |
+ } |
+ |
+ bool operator!=(const AtomicEnumSet& set) const { |
+ return ToIntegral() != set.ToIntegral(); |
+ } |
+ |
+ AtomicEnumSet<E> operator|(const AtomicEnumSet& set) const { |
+ return AtomicEnumSet<E>(ToIntegral() | set.ToIntegral()); |
+ } |
+ |
+// The following operations modify the underlying storage. |
+ |
+#define ATOMIC_SET_WRITE(OP, NEW_VAL) \ |
+ do { \ |
+ base::AtomicWord old; \ |
+ do { \ |
+ old = base::Acquire_Load(&bits_); \ |
+ } while (base::Release_CompareAndSwap(&bits_, old, old OP NEW_VAL) != \ |
+ old); \ |
+ } while (false) |
+ |
+ void Add(E element) { ATOMIC_SET_WRITE(|, Mask(element)); } |
+ |
+ void Add(const AtomicEnumSet& set) { ATOMIC_SET_WRITE(|, set.ToIntegral()); } |
+ |
+ void Remove(E element) { ATOMIC_SET_WRITE(&, Mask(element)); } |
+ |
+ void Remove(const AtomicEnumSet& set) { |
+ ATOMIC_SET_WRITE(&, ~set.ToIntegral()); |
+ } |
+ |
+ void Intersect(const AtomicEnumSet& set) { |
+ ATOMIC_SET_WRITE(&, set.ToIntegral()); |
+ } |
+ |
+#undef ATOMIC_SET_OP |
+ |
+ private: |
+ // Check whether there's enough storage to hold E. |
+ STATIC_ASSERT(E::kLastValue < (sizeof(base::AtomicWord) * CHAR_BIT)); |
+ |
+ V8_INLINE base::AtomicWord ToIntegral() const { |
+ return base::NoBarrier_Load(&bits_); |
+ } |
+ |
+ V8_INLINE base::AtomicWord Mask(E element) const { |
+ return static_cast<base::AtomicWord>(1) << element; |
+ } |
+ |
+ base::AtomicWord bits_; |
+}; |
+ |
+ |
+// Flag using enums atomically. |
+template <class E> |
+class AtomicEnumFlag { |
+ public: |
+ explicit AtomicEnumFlag(E initial) : value_(initial) {} |
+ |
+ V8_INLINE E Value() { return static_cast<E>(base::NoBarrier_Load(&value_)); } |
+ |
+ V8_INLINE bool TrySetValue(E old_value, E new_value) { |
+ return base::NoBarrier_CompareAndSwap( |
+ &value_, static_cast<base::AtomicWord>(old_value), |
+ static_cast<base::AtomicWord>(new_value)) == |
+ static_cast<base::AtomicWord>(old_value); |
+ } |
+ |
+ private: |
+ base::AtomicWord value_; |
+}; |
+ |
+} // namespace internal |
+} // namespace v8 |
+ |
+#endif // #define V8_ATOMIC_UTILS_H_ |