1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved. 2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file. 4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifndef V8_ATOMIC_UTILS_H_ 6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define V8_ATOMIC_UTILS_H_ 7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include <limits.h> 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/base/atomicops.h" 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/base/macros.h" 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 { 14bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace base { 15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <class T> 17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass AtomicNumber { 18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public: 19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch AtomicNumber() : value_(0) {} 20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch explicit AtomicNumber(T initial) : value_(initial) {} 21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 22f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Returns the value after incrementing. 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch V8_INLINE T Increment(T increment) { 24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return static_cast<T>(base::Barrier_AtomicIncrement( 25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &value_, static_cast<base::AtomicWord>(increment))); 26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 28f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Returns the value after decrementing. 29f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch V8_INLINE T Decrement(T decrement) { 30f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return static_cast<T>(base::Barrier_AtomicIncrement( 31f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch &value_, -static_cast<base::AtomicWord>(decrement))); 32f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 33f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 3462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch V8_INLINE T Value() const { 3562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return static_cast<T>(base::Acquire_Load(&value_)); 3662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch V8_INLINE void SetValue(T new_value) { 39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::Release_Store(&value_, static_cast<base::AtomicWord>(new_value)); 40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch V8_INLINE T operator=(T value) { 43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetValue(value); 44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return value; 45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 47f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch V8_INLINE T operator+=(T value) { return Increment(value); } 48f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch V8_INLINE T operator-=(T value) { return Decrement(value); } 49f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private: 51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); 52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::AtomicWord value_; 54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 56c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// This type uses no barrier accessors to change atomic word. Be careful with 57c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// data races. 58c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochtemplate <typename T> 59c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochclass NoBarrierAtomicValue { 60c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch public: 61c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch NoBarrierAtomicValue() : value_(0) {} 62c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 63c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch explicit NoBarrierAtomicValue(T initial) 64c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch : value_(cast_helper<T>::to_storage_type(initial)) {} 65c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 66c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch static NoBarrierAtomicValue* FromAddress(void* address) { 67c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return reinterpret_cast<base::NoBarrierAtomicValue<T>*>(address); 68c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 69c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 70c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch V8_INLINE bool TrySetValue(T old_value, T new_value) { 71c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return base::NoBarrier_CompareAndSwap( 72c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &value_, cast_helper<T>::to_storage_type(old_value), 73c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch cast_helper<T>::to_storage_type(new_value)) == 74c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch cast_helper<T>::to_storage_type(old_value); 75c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 76c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 77c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch V8_INLINE T Value() const { 78c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return cast_helper<T>::to_return_type(base::NoBarrier_Load(&value_)); 79c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 80c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 81c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch V8_INLINE void SetValue(T new_value) { 82c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch base::NoBarrier_Store(&value_, cast_helper<T>::to_storage_type(new_value)); 83c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 84c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 85c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch private: 86c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); 87c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 88c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch template <typename S> 89c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch struct cast_helper { 90c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch static base::AtomicWord to_storage_type(S value) { 91c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return static_cast<base::AtomicWord>(value); 92c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 93c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch static S to_return_type(base::AtomicWord value) { 94c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return static_cast<S>(value); 95c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 96c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch }; 97c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 98c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch template <typename S> 99c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch struct cast_helper<S*> { 100c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch static base::AtomicWord to_storage_type(S* value) { 101c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return reinterpret_cast<base::AtomicWord>(value); 102c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 103c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch static S* to_return_type(base::AtomicWord value) { 104c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return reinterpret_cast<S*>(value); 105c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 106c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch }; 107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch base::AtomicWord value_; 109c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}; 110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Flag using T atomically. Also accepts void* as T. 112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <typename T> 113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass AtomicValue { 114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public: 115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch AtomicValue() : value_(0) {} 116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch explicit AtomicValue(T initial) 118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : value_(cast_helper<T>::to_storage_type(initial)) {} 119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch V8_INLINE T Value() const { 121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return cast_helper<T>::to_return_type(base::Acquire_Load(&value_)); 122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch V8_INLINE bool TrySetValue(T old_value, T new_value) { 125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return base::Release_CompareAndSwap( 126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &value_, cast_helper<T>::to_storage_type(old_value), 127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch cast_helper<T>::to_storage_type(new_value)) == 128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch cast_helper<T>::to_storage_type(old_value); 129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch V8_INLINE void SetBits(T bits, T mask) { 132c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_EQ(bits & ~mask, static_cast<T>(0)); 133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch T old_value; 134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch T new_value; 135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch do { 136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch old_value = Value(); 137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch new_value = (old_value & ~mask) | bits; 138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } while (!TrySetValue(old_value, new_value)); 139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch V8_INLINE void SetBit(int bit) { 142f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SetBits(static_cast<T>(1) << bit, static_cast<T>(1) << bit); 143f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 145f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch V8_INLINE void ClearBit(int bit) { SetBits(0, 1 << bit); } 146f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch V8_INLINE void SetValue(T new_value) { 148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::Release_Store(&value_, cast_helper<T>::to_storage_type(new_value)); 149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private: 152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); 153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch template <typename S> 155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch struct cast_helper { 156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static base::AtomicWord to_storage_type(S value) { 157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return static_cast<base::AtomicWord>(value); 158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static S to_return_type(base::AtomicWord value) { 160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return static_cast<S>(value); 161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch template <typename S> 165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch struct cast_helper<S*> { 166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static base::AtomicWord to_storage_type(S* value) { 167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return reinterpret_cast<base::AtomicWord>(value); 168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static S* to_return_type(base::AtomicWord value) { 170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return reinterpret_cast<S*>(value); 171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::AtomicWord value_; 175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// See utils.h for EnumSet. Storage is always base::AtomicWord. 179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Requirements on E: 180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// - No explicit values. 181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// - E::kLastValue defined to be the last actually used value. 182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// 183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Example: 184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// enum E { kA, kB, kC, kLastValue = kC }; 185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <class E> 186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass AtomicEnumSet { 187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public: 188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch explicit AtomicEnumSet(base::AtomicWord bits = 0) : bits_(bits) {} 189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool IsEmpty() const { return ToIntegral() == 0; } 191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool Contains(E element) const { return (ToIntegral() & Mask(element)) != 0; } 193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool ContainsAnyOf(const AtomicEnumSet& set) const { 194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return (ToIntegral() & set.ToIntegral()) != 0; 195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void RemoveAll() { base::Release_Store(&bits_, 0); } 198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool operator==(const AtomicEnumSet& set) const { 200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return ToIntegral() == set.ToIntegral(); 201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool operator!=(const AtomicEnumSet& set) const { 204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return ToIntegral() != set.ToIntegral(); 205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch AtomicEnumSet<E> operator|(const AtomicEnumSet& set) const { 208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return AtomicEnumSet<E>(ToIntegral() | set.ToIntegral()); 209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// The following operations modify the underlying storage. 212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define ATOMIC_SET_WRITE(OP, NEW_VAL) \ 214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch do { \ 215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::AtomicWord old; \ 216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch do { \ 217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch old = base::Acquire_Load(&bits_); \ 218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } while (base::Release_CompareAndSwap(&bits_, old, old OP NEW_VAL) != \ 219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch old); \ 220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } while (false) 221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Add(E element) { ATOMIC_SET_WRITE(|, Mask(element)); } 223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Add(const AtomicEnumSet& set) { ATOMIC_SET_WRITE(|, set.ToIntegral()); } 225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Remove(E element) { ATOMIC_SET_WRITE(&, ~Mask(element)); } 227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Remove(const AtomicEnumSet& set) { 229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ATOMIC_SET_WRITE(&, ~set.ToIntegral()); 230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Intersect(const AtomicEnumSet& set) { 233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ATOMIC_SET_WRITE(&, set.ToIntegral()); 234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef ATOMIC_SET_OP 237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private: 239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check whether there's enough storage to hold E. 240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(E::kLastValue < (sizeof(base::AtomicWord) * CHAR_BIT)); 241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch V8_INLINE base::AtomicWord ToIntegral() const { 243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return base::Acquire_Load(&bits_); 244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch V8_INLINE base::AtomicWord Mask(E element) const { 247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return static_cast<base::AtomicWord>(1) << element; 248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::AtomicWord bits_; 251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 253bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} // namespace base 254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif // #define V8_ATOMIC_UTILS_H_ 257