Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1658)

Side by Side Diff: src/atomic-utils.h

Issue 1324153003: Add template parameter and unittests to atomic utils. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fighting c++ Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/heap/heap.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_ATOMIC_UTILS_H_ 5 #ifndef V8_ATOMIC_UTILS_H_
6 #define V8_ATOMIC_UTILS_H_ 6 #define V8_ATOMIC_UTILS_H_
7 7
8 #include <limits.h> 8 #include <limits.h>
9 9
10 #include "src/base/atomicops.h" 10 #include "src/base/atomicops.h"
11 #include "src/base/macros.h" 11 #include "src/base/macros.h"
12 12
13 namespace v8 { 13 namespace v8 {
14 namespace internal { 14 namespace internal {
15 15
16 class AtomicValue { 16 template <class T>
17 class AtomicNumber {
17 public: 18 public:
18 AtomicValue() : value_(0) {} 19 AtomicNumber() : value_(0) {}
19 explicit AtomicValue(base::AtomicWord initial) : value_(initial) {} 20 explicit AtomicNumber(T initial) : value_(initial) {}
20 21
21 V8_INLINE void Increment(base::AtomicWord increment) { 22 V8_INLINE void Increment(T increment) {
22 base::NoBarrier_AtomicIncrement(&value_, increment); 23 base::NoBarrier_AtomicIncrement(&value_,
24 static_cast<base::AtomicWord>(increment));
23 } 25 }
24 26
25 V8_INLINE base::AtomicWord Value() { return base::NoBarrier_Load(&value_); } 27 V8_INLINE T Value() { return static_cast<T>(base::NoBarrier_Load(&value_)); }
26 28
27 V8_INLINE void SetValue(base::AtomicWord new_value) { 29 V8_INLINE void SetValue(T new_value) {
28 base::NoBarrier_Store(&value_, new_value); 30 base::NoBarrier_Store(&value_, static_cast<base::AtomicWord>(new_value));
29 } 31 }
30 32
31 private: 33 private:
34 STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
35
32 base::AtomicWord value_; 36 base::AtomicWord value_;
33 }; 37 };
34 38
39
40 // Flag using T atomically. Also accepts void* as T.
41 template <typename T>
42 class AtomicValue {
43 public:
44 explicit AtomicValue(T initial)
45 : value_(cast_helper<T>::to_storage_type(initial)) {}
46
47 V8_INLINE T Value() {
48 return cast_helper<T>::to_return_type(base::NoBarrier_Load(&value_));
49 }
50
51 V8_INLINE bool TrySetValue(T old_value, T new_value) {
52 return base::NoBarrier_CompareAndSwap(
53 &value_, cast_helper<T>::to_storage_type(old_value),
54 cast_helper<T>::to_storage_type(new_value)) ==
55 cast_helper<T>::to_storage_type(old_value);
56 }
57
58 V8_INLINE T /*old_value*/ SetValue(T new_value) {
59 return cast_helper<T>::to_return_type(base::NoBarrier_AtomicExchange(
60 &value_, cast_helper<T>::to_storage_type(new_value)));
61 }
62
63 private:
64 STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
65
66 template <typename S>
67 struct cast_helper {
Michael Starzinger 2015/09/04 13:28:46 Got a rhyme for you: You sneaky C++ wiz, I am fin
Michael Lippautz 2015/09/04 13:37:12 Hah! Good enough for me!
68 static base::AtomicWord to_storage_type(S value) {
69 return static_cast<base::AtomicWord>(value);
70 }
71 static S to_return_type(base::AtomicWord value) {
72 return static_cast<S>(value);
73 }
74 };
75
76 template <typename S>
77 struct cast_helper<S*> {
78 static base::AtomicWord to_storage_type(S* value) {
79 return reinterpret_cast<base::AtomicWord>(value);
80 }
81 static S* to_return_type(base::AtomicWord value) {
82 return reinterpret_cast<S*>(value);
83 }
84 };
85
86 base::AtomicWord value_;
87 };
88
35 89
36 // See utils.h for EnumSet. Storage is always base::AtomicWord. 90 // See utils.h for EnumSet. Storage is always base::AtomicWord.
37 // Requirements on E: 91 // Requirements on E:
38 // - No explicit values. 92 // - No explicit values.
39 // - E::kLastValue defined to be the last actually used value. 93 // - E::kLastValue defined to be the last actually used value.
40 // 94 //
41 // Example: 95 // Example:
42 // enum E { kA, kB, kC, kLastValue = kC }; 96 // enum E { kA, kB, kC, kLastValue = kC };
43 template <class E> 97 template <class E>
44 class AtomicEnumSet { 98 class AtomicEnumSet {
(...skipping 30 matching lines...) Expand all
75 do { \ 129 do { \
76 old = base::Acquire_Load(&bits_); \ 130 old = base::Acquire_Load(&bits_); \
77 } while (base::Release_CompareAndSwap(&bits_, old, old OP NEW_VAL) != \ 131 } while (base::Release_CompareAndSwap(&bits_, old, old OP NEW_VAL) != \
78 old); \ 132 old); \
79 } while (false) 133 } while (false)
80 134
81 void Add(E element) { ATOMIC_SET_WRITE(|, Mask(element)); } 135 void Add(E element) { ATOMIC_SET_WRITE(|, Mask(element)); }
82 136
83 void Add(const AtomicEnumSet& set) { ATOMIC_SET_WRITE(|, set.ToIntegral()); } 137 void Add(const AtomicEnumSet& set) { ATOMIC_SET_WRITE(|, set.ToIntegral()); }
84 138
85 void Remove(E element) { ATOMIC_SET_WRITE(&, Mask(element)); } 139 void Remove(E element) { ATOMIC_SET_WRITE(&, ~Mask(element)); }
86 140
87 void Remove(const AtomicEnumSet& set) { 141 void Remove(const AtomicEnumSet& set) {
88 ATOMIC_SET_WRITE(&, ~set.ToIntegral()); 142 ATOMIC_SET_WRITE(&, ~set.ToIntegral());
89 } 143 }
90 144
91 void Intersect(const AtomicEnumSet& set) { 145 void Intersect(const AtomicEnumSet& set) {
92 ATOMIC_SET_WRITE(&, set.ToIntegral()); 146 ATOMIC_SET_WRITE(&, set.ToIntegral());
93 } 147 }
94 148
95 #undef ATOMIC_SET_OP 149 #undef ATOMIC_SET_OP
96 150
97 private: 151 private:
98 // Check whether there's enough storage to hold E. 152 // Check whether there's enough storage to hold E.
99 STATIC_ASSERT(E::kLastValue < (sizeof(base::AtomicWord) * CHAR_BIT)); 153 STATIC_ASSERT(E::kLastValue < (sizeof(base::AtomicWord) * CHAR_BIT));
100 154
101 V8_INLINE base::AtomicWord ToIntegral() const { 155 V8_INLINE base::AtomicWord ToIntegral() const {
102 return base::NoBarrier_Load(&bits_); 156 return base::NoBarrier_Load(&bits_);
103 } 157 }
104 158
105 V8_INLINE base::AtomicWord Mask(E element) const { 159 V8_INLINE base::AtomicWord Mask(E element) const {
106 return static_cast<base::AtomicWord>(1) << element; 160 return static_cast<base::AtomicWord>(1) << element;
107 } 161 }
108 162
109 base::AtomicWord bits_; 163 base::AtomicWord bits_;
110 }; 164 };
111 165
112
113 // Flag using enums atomically.
114 template <class E>
115 class AtomicEnumFlag {
116 public:
117 explicit AtomicEnumFlag(E initial) : value_(initial) {}
118
119 V8_INLINE E Value() { return static_cast<E>(base::NoBarrier_Load(&value_)); }
120
121 V8_INLINE bool TrySetValue(E old_value, E new_value) {
122 return base::NoBarrier_CompareAndSwap(
123 &value_, static_cast<base::AtomicWord>(old_value),
124 static_cast<base::AtomicWord>(new_value)) ==
125 static_cast<base::AtomicWord>(old_value);
126 }
127
128 private:
129 base::AtomicWord value_;
130 };
131
132 } // namespace internal 166 } // namespace internal
133 } // namespace v8 167 } // namespace v8
134 168
135 #endif // #define V8_ATOMIC_UTILS_H_ 169 #endif // #define V8_ATOMIC_UTILS_H_
OLDNEW
« no previous file with comments | « no previous file | src/heap/heap.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698