V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
atomic-utils.h
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_BASE_ATOMIC_UTILS_H_
6 #define V8_BASE_ATOMIC_UTILS_H_
7 
8 #include <limits.h>
9 #include <type_traits>
10 
11 #include "src/base/atomicops.h"
12 #include "src/base/macros.h"
13 
14 namespace v8 {
15 namespace base {
16 
17 // Deprecated. Use std::atomic<T> for new code.
18 // Flag using T atomically. Also accepts void* as T.
19 template <typename T>
20 class AtomicValue {
21  public:
22  AtomicValue() : value_(0) {}
23 
24  explicit AtomicValue(T initial)
25  : value_(cast_helper<T>::to_storage_type(initial)) {}
26 
27  V8_INLINE T Value() const {
28  return cast_helper<T>::to_return_type(base::Acquire_Load(&value_));
29  }
30 
31  V8_INLINE void SetValue(T new_value) {
32  base::Release_Store(&value_, cast_helper<T>::to_storage_type(new_value));
33  }
34 
35  private:
36  STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
37 
38  template <typename S>
39  struct cast_helper {
40  static base::AtomicWord to_storage_type(S value) {
41  return static_cast<base::AtomicWord>(value);
42  }
43  static S to_return_type(base::AtomicWord value) {
44  return static_cast<S>(value);
45  }
46  };
47 
48  template <typename S>
49  struct cast_helper<S*> {
50  static base::AtomicWord to_storage_type(S* value) {
51  return reinterpret_cast<base::AtomicWord>(value);
52  }
53  static S* to_return_type(base::AtomicWord value) {
54  return reinterpret_cast<S*>(value);
55  }
56  };
57 
58  base::AtomicWord value_;
59 };
60 
61 // Provides atomic operations for a values stored at some address.
62 template <typename TAtomicStorageType>
63 class AsAtomicImpl {
64  public:
65  using AtomicStorageType = TAtomicStorageType;
66 
67  template <typename T>
68  static T Acquire_Load(T* addr) {
69  STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
70  return cast_helper<T>::to_return_type(
71  base::Acquire_Load(to_storage_addr(addr)));
72  }
73 
74  template <typename T>
75  static T Relaxed_Load(T* addr) {
76  STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
77  return cast_helper<T>::to_return_type(
78  base::Relaxed_Load(to_storage_addr(addr)));
79  }
80 
81  template <typename T>
82  static void Release_Store(T* addr,
83  typename std::remove_reference<T>::type new_value) {
84  STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
85  base::Release_Store(to_storage_addr(addr),
86  cast_helper<T>::to_storage_type(new_value));
87  }
88 
89  template <typename T>
90  static void Relaxed_Store(T* addr,
91  typename std::remove_reference<T>::type new_value) {
92  STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
93  base::Relaxed_Store(to_storage_addr(addr),
94  cast_helper<T>::to_storage_type(new_value));
95  }
96 
97  template <typename T>
98  static T Release_CompareAndSwap(
99  T* addr, typename std::remove_reference<T>::type old_value,
100  typename std::remove_reference<T>::type new_value) {
101  STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
102  return cast_helper<T>::to_return_type(base::Release_CompareAndSwap(
103  to_storage_addr(addr), cast_helper<T>::to_storage_type(old_value),
104  cast_helper<T>::to_storage_type(new_value)));
105  }
106 
107  // Atomically sets bits selected by the mask to the given value.
108  // Returns false if the bits are already set as needed.
109  template <typename T>
110  static bool SetBits(T* addr, T bits, T mask) {
111  STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
112  DCHECK_EQ(bits & ~mask, static_cast<T>(0));
113  T old_value;
114  T new_value;
115  do {
116  old_value = Relaxed_Load(addr);
117  if ((old_value & mask) == bits) return false;
118  new_value = (old_value & ~mask) | bits;
119  } while (Release_CompareAndSwap(addr, old_value, new_value) != old_value);
120  return true;
121  }
122 
123  private:
124  template <typename U>
125  struct cast_helper {
126  static AtomicStorageType to_storage_type(U value) {
127  return static_cast<AtomicStorageType>(value);
128  }
129  static U to_return_type(AtomicStorageType value) {
130  return static_cast<U>(value);
131  }
132  };
133 
134  template <typename U>
135  struct cast_helper<U*> {
136  static AtomicStorageType to_storage_type(U* value) {
137  return reinterpret_cast<AtomicStorageType>(value);
138  }
139  static U* to_return_type(AtomicStorageType value) {
140  return reinterpret_cast<U*>(value);
141  }
142  };
143 
144  template <typename T>
145  static AtomicStorageType* to_storage_addr(T* value) {
146  return reinterpret_cast<AtomicStorageType*>(value);
147  }
148  template <typename T>
149  static const AtomicStorageType* to_storage_addr(const T* value) {
150  return reinterpret_cast<const AtomicStorageType*>(value);
151  }
152 };
153 
157 
158 // This is similar to AsAtomicWord but it explicitly deletes functionality
159 // provided atomic access to bit representation of stored values.
160 template <typename TAtomicStorageType>
161 class AsAtomicPointerImpl : public AsAtomicImpl<TAtomicStorageType> {
162  public:
163  template <typename T>
164  static bool SetBits(T* addr, T bits, T mask) = delete;
165 };
166 
168 
169 template <typename T,
170  typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
171 inline void CheckedIncrement(std::atomic<T>* number, T amount) {
172  const T old = number->fetch_add(amount);
173  DCHECK_GE(old + amount, old);
174  USE(old);
175 }
176 
177 template <typename T,
178  typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
179 inline void CheckedDecrement(std::atomic<T>* number, T amount) {
180  const T old = number->fetch_sub(amount);
181  DCHECK_GE(old, amount);
182  USE(old);
183 }
184 
185 } // namespace base
186 } // namespace v8
187 
188 #endif // V8_BASE_ATOMIC_UTILS_H_
Definition: v8.h:2119
Definition: libplatform.h:13