Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ new/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
1 1 /*
2 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 3 *
4 4 * This code is free software; you can redistribute it and/or modify it
5 5 * under the terms of the GNU General Public License version 2 only, as
6 6 * published by the Free Software Foundation. Oracle designates this
7 7 * particular file as subject to the "Classpath" exception as provided
8 8 * by Oracle in the LICENSE file that accompanied this code.
9 9 *
10 10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 13 * version 2 for more details (a copy is included in the LICENSE file that
14 14 * accompanied this code).
15 15 *
16 16 * You should have received a copy of the GNU General Public License version
17 17 * 2 along with this work; if not, write to the Free Software Foundation,
18 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 19 *
20 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 21 * or visit www.oracle.com if you need additional information or have any
22 22 * questions.
23 23 */
24 24
25 25 /*
26 26 * This file is available under and governed by the GNU General Public
27 27 * License version 2 only, as published by the Free Software Foundation.
28 28 * However, the following notice accompanied the original version of this
29 29 * file:
30 30 *
31 31 * Written by Doug Lea with assistance from members of JCP JSR-166
32 32 * Expert Group and released to the public domain, as explained at
33 33 * http://creativecommons.org/licenses/publicdomain
34 34 */
35 35
36 36 package java.util.concurrent.atomic;
37 37 import sun.misc.Unsafe;
38 38 import java.lang.reflect.*;
39 39
40 40 /**
41 41 * A reflection-based utility that enables atomic updates to
42 42 * designated {@code volatile int} fields of designated classes.
43 43 * This class is designed for use in atomic data structures in which
44 44 * several fields of the same node are independently subject to atomic
45 45 * updates.
46 46 *
47 47 * <p>Note that the guarantees of the {@code compareAndSet}
↓ open down ↓ |
47 lines elided |
↑ open up ↑ |
48 48 * method in this class are weaker than in other atomic classes.
49 49 * Because this class cannot ensure that all uses of the field
50 50 * are appropriate for purposes of atomic access, it can
51 51 * guarantee atomicity only with respect to other invocations of
52 52 * {@code compareAndSet} and {@code set} on the same updater.
53 53 *
54 54 * @since 1.5
55 55 * @author Doug Lea
56 56 * @param <T> The type of the object holding the updatable field
57 57 */
58 -public abstract class AtomicIntegerFieldUpdater<T> {
58 +public abstract class AtomicIntegerFieldUpdater<T> {
59 59 /**
60 60 * Creates and returns an updater for objects with the given field.
61 61 * The Class argument is needed to check that reflective types and
62 62 * generic types match.
63 63 *
64 64 * @param tclass the class of the objects holding the field
65 65 * @param fieldName the name of the field to be updated
66 66 * @return the updater
67 67 * @throws IllegalArgumentException if the field is not a
68 68 * volatile integer type
69 69 * @throws RuntimeException with a nested reflection-based
70 70 * exception if the class does not hold field or is the wrong type
71 71 */
72 72 public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
73 73 return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName);
74 74 }
75 75
76 76 /**
77 77 * Protected do-nothing constructor for use by subclasses.
78 78 */
79 79 protected AtomicIntegerFieldUpdater() {
80 80 }
81 81
82 82 /**
83 83 * Atomically sets the field of the given object managed by this updater
84 84 * to the given updated value if the current value {@code ==} the
85 85 * expected value. This method is guaranteed to be atomic with respect to
86 86 * other calls to {@code compareAndSet} and {@code set}, but not
87 87 * necessarily with respect to other changes in the field.
88 88 *
89 89 * @param obj An object whose field to conditionally set
90 90 * @param expect the expected value
91 91 * @param update the new value
92 92 * @return true if successful
93 93 * @throws ClassCastException if {@code obj} is not an instance
94 94 * of the class possessing the field established in the constructor
95 95 */
96 96 public abstract boolean compareAndSet(T obj, int expect, int update);
97 97
98 98 /**
99 99 * Atomically sets the field of the given object managed by this updater
100 100 * to the given updated value if the current value {@code ==} the
101 101 * expected value. This method is guaranteed to be atomic with respect to
102 102 * other calls to {@code compareAndSet} and {@code set}, but not
103 103 * necessarily with respect to other changes in the field.
104 104 *
105 105 * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
106 106 * and does not provide ordering guarantees, so is only rarely an
107 107 * appropriate alternative to {@code compareAndSet}.
108 108 *
109 109 * @param obj An object whose field to conditionally set
110 110 * @param expect the expected value
111 111 * @param update the new value
112 112 * @return true if successful
113 113 * @throws ClassCastException if {@code obj} is not an instance
114 114 * of the class possessing the field established in the constructor
115 115 */
116 116 public abstract boolean weakCompareAndSet(T obj, int expect, int update);
117 117
118 118 /**
119 119 * Sets the field of the given object managed by this updater to the
120 120 * given updated value. This operation is guaranteed to act as a volatile
121 121 * store with respect to subsequent invocations of {@code compareAndSet}.
122 122 *
123 123 * @param obj An object whose field to set
124 124 * @param newValue the new value
125 125 */
126 126 public abstract void set(T obj, int newValue);
127 127
128 128 /**
129 129 * Eventually sets the field of the given object managed by this
130 130 * updater to the given updated value.
131 131 *
132 132 * @param obj An object whose field to set
133 133 * @param newValue the new value
134 134 * @since 1.6
135 135 */
136 136 public abstract void lazySet(T obj, int newValue);
137 137
138 138
139 139 /**
140 140 * Gets the current value held in the field of the given object managed
141 141 * by this updater.
142 142 *
143 143 * @param obj An object whose field to get
144 144 * @return the current value
145 145 */
146 146 public abstract int get(T obj);
147 147
148 148 /**
149 149 * Atomically sets the field of the given object managed by this updater
150 150 * to the given value and returns the old value.
151 151 *
152 152 * @param obj An object whose field to get and set
153 153 * @param newValue the new value
154 154 * @return the previous value
155 155 */
156 156 public int getAndSet(T obj, int newValue) {
157 157 for (;;) {
158 158 int current = get(obj);
159 159 if (compareAndSet(obj, current, newValue))
160 160 return current;
161 161 }
162 162 }
163 163
164 164 /**
165 165 * Atomically increments by one the current value of the field of the
166 166 * given object managed by this updater.
167 167 *
168 168 * @param obj An object whose field to get and set
169 169 * @return the previous value
170 170 */
171 171 public int getAndIncrement(T obj) {
172 172 for (;;) {
173 173 int current = get(obj);
174 174 int next = current + 1;
175 175 if (compareAndSet(obj, current, next))
176 176 return current;
177 177 }
178 178 }
179 179
180 180 /**
181 181 * Atomically decrements by one the current value of the field of the
182 182 * given object managed by this updater.
183 183 *
184 184 * @param obj An object whose field to get and set
185 185 * @return the previous value
186 186 */
187 187 public int getAndDecrement(T obj) {
188 188 for (;;) {
189 189 int current = get(obj);
190 190 int next = current - 1;
191 191 if (compareAndSet(obj, current, next))
192 192 return current;
193 193 }
194 194 }
195 195
196 196 /**
197 197 * Atomically adds the given value to the current value of the field of
198 198 * the given object managed by this updater.
199 199 *
200 200 * @param obj An object whose field to get and set
201 201 * @param delta the value to add
202 202 * @return the previous value
203 203 */
204 204 public int getAndAdd(T obj, int delta) {
205 205 for (;;) {
206 206 int current = get(obj);
207 207 int next = current + delta;
208 208 if (compareAndSet(obj, current, next))
209 209 return current;
210 210 }
211 211 }
212 212
213 213 /**
214 214 * Atomically increments by one the current value of the field of the
215 215 * given object managed by this updater.
216 216 *
217 217 * @param obj An object whose field to get and set
218 218 * @return the updated value
219 219 */
220 220 public int incrementAndGet(T obj) {
221 221 for (;;) {
222 222 int current = get(obj);
223 223 int next = current + 1;
224 224 if (compareAndSet(obj, current, next))
225 225 return next;
226 226 }
227 227 }
228 228
229 229 /**
230 230 * Atomically decrements by one the current value of the field of the
231 231 * given object managed by this updater.
232 232 *
233 233 * @param obj An object whose field to get and set
234 234 * @return the updated value
235 235 */
236 236 public int decrementAndGet(T obj) {
237 237 for (;;) {
238 238 int current = get(obj);
239 239 int next = current - 1;
240 240 if (compareAndSet(obj, current, next))
241 241 return next;
242 242 }
243 243 }
244 244
245 245 /**
246 246 * Atomically adds the given value to the current value of the field of
247 247 * the given object managed by this updater.
248 248 *
249 249 * @param obj An object whose field to get and set
250 250 * @param delta the value to add
251 251 * @return the updated value
252 252 */
253 253 public int addAndGet(T obj, int delta) {
254 254 for (;;) {
255 255 int current = get(obj);
256 256 int next = current + delta;
257 257 if (compareAndSet(obj, current, next))
258 258 return next;
259 259 }
260 260 }
261 261
262 262 /**
263 263 * Standard hotspot implementation using intrinsics
264 264 */
265 265 private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> {
266 266 private static final Unsafe unsafe = Unsafe.getUnsafe();
267 267 private final long offset;
268 268 private final Class<T> tclass;
269 269 private final Class cclass;
270 270
271 271 AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName) {
↓ open down ↓ |
203 lines elided |
↑ open up ↑ |
272 272 Field field = null;
273 273 Class caller = null;
274 274 int modifiers = 0;
275 275 try {
276 276 field = tclass.getDeclaredField(fieldName);
277 277 caller = sun.reflect.Reflection.getCallerClass(3);
278 278 modifiers = field.getModifiers();
279 279 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
280 280 caller, tclass, null, modifiers);
281 281 sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
282 - } catch(Exception ex) {
282 + } catch (Exception ex) {
283 283 throw new RuntimeException(ex);
284 284 }
285 285
286 286 Class fieldt = field.getType();
287 287 if (fieldt != int.class)
288 288 throw new IllegalArgumentException("Must be integer type");
289 289
290 290 if (!Modifier.isVolatile(modifiers))
291 291 throw new IllegalArgumentException("Must be volatile type");
292 292
293 293 this.cclass = (Modifier.isProtected(modifiers) &&
294 294 caller != tclass) ? caller : null;
295 295 this.tclass = tclass;
296 296 offset = unsafe.objectFieldOffset(field);
297 297 }
298 298
299 299 private void fullCheck(T obj) {
300 300 if (!tclass.isInstance(obj))
301 301 throw new ClassCastException();
302 302 if (cclass != null)
303 303 ensureProtectedAccess(obj);
304 304 }
305 305
306 306 public boolean compareAndSet(T obj, int expect, int update) {
307 307 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
308 308 return unsafe.compareAndSwapInt(obj, offset, expect, update);
309 309 }
310 310
311 311 public boolean weakCompareAndSet(T obj, int expect, int update) {
312 312 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
313 313 return unsafe.compareAndSwapInt(obj, offset, expect, update);
314 314 }
315 315
316 316 public void set(T obj, int newValue) {
317 317 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
318 318 unsafe.putIntVolatile(obj, offset, newValue);
319 319 }
320 320
321 321 public void lazySet(T obj, int newValue) {
322 322 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
323 323 unsafe.putOrderedInt(obj, offset, newValue);
324 324 }
325 325
326 326 public final int get(T obj) {
327 327 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
328 328 return unsafe.getIntVolatile(obj, offset);
329 329 }
330 330
331 331 private void ensureProtectedAccess(T obj) {
332 332 if (cclass.isInstance(obj)) {
333 333 return;
334 334 }
335 335 throw new RuntimeException(
336 336 new IllegalAccessException("Class " +
337 337 cclass.getName() +
338 338 " can not access a protected member of class " +
339 339 tclass.getName() +
340 340 " using an instance of " +
341 341 obj.getClass().getName()
342 342 )
343 343 );
344 344 }
345 345 }
346 346 }
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX