Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ new/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.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 long} 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 AtomicLongFieldUpdater<T> {
58 +public abstract class AtomicLongFieldUpdater<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 long 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> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
73 73 if (AtomicLong.VM_SUPPORTS_LONG_CAS)
74 74 return new CASUpdater<U>(tclass, fieldName);
75 75 else
76 76 return new LockedUpdater<U>(tclass, fieldName);
77 77 }
78 78
79 79 /**
80 80 * Protected do-nothing constructor for use by subclasses.
81 81 */
82 82 protected AtomicLongFieldUpdater() {
83 83 }
84 84
85 85 /**
86 86 * Atomically sets the field of the given object managed by this updater
87 87 * to the given updated value if the current value {@code ==} the
88 88 * expected value. This method is guaranteed to be atomic with respect to
89 89 * other calls to {@code compareAndSet} and {@code set}, but not
90 90 * necessarily with respect to other changes in the field.
91 91 *
92 92 * @param obj An object whose field to conditionally set
93 93 * @param expect the expected value
94 94 * @param update the new value
95 95 * @return true if successful.
96 96 * @throws ClassCastException if {@code obj} is not an instance
97 97 * of the class possessing the field established in the constructor.
98 98 */
99 99 public abstract boolean compareAndSet(T obj, long expect, long update);
100 100
101 101 /**
102 102 * Atomically sets the field of the given object managed by this updater
103 103 * to the given updated value if the current value {@code ==} the
104 104 * expected value. This method is guaranteed to be atomic with respect to
105 105 * other calls to {@code compareAndSet} and {@code set}, but not
106 106 * necessarily with respect to other changes in the field.
107 107 *
108 108 * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
109 109 * and does not provide ordering guarantees, so is only rarely an
110 110 * appropriate alternative to {@code compareAndSet}.
111 111 *
112 112 * @param obj An object whose field to conditionally set
113 113 * @param expect the expected value
114 114 * @param update the new value
115 115 * @return true if successful.
116 116 * @throws ClassCastException if {@code obj} is not an instance
117 117 * of the class possessing the field established in the constructor.
118 118 */
119 119 public abstract boolean weakCompareAndSet(T obj, long expect, long update);
120 120
121 121 /**
122 122 * Sets the field of the given object managed by this updater to the
123 123 * given updated value. This operation is guaranteed to act as a volatile
124 124 * store with respect to subsequent invocations of {@code compareAndSet}.
125 125 *
126 126 * @param obj An object whose field to set
127 127 * @param newValue the new value
128 128 */
129 129 public abstract void set(T obj, long newValue);
130 130
131 131 /**
132 132 * Eventually sets the field of the given object managed by this
133 133 * updater to the given updated value.
134 134 *
135 135 * @param obj An object whose field to set
136 136 * @param newValue the new value
137 137 * @since 1.6
138 138 */
139 139 public abstract void lazySet(T obj, long newValue);
140 140
141 141 /**
142 142 * Gets the current value held in the field of the given object managed
143 143 * by this updater.
144 144 *
145 145 * @param obj An object whose field to get
146 146 * @return the current value
147 147 */
148 148 public abstract long get(T obj);
149 149
150 150 /**
151 151 * Atomically sets the field of the given object managed by this updater
152 152 * to the given value and returns the old value.
153 153 *
154 154 * @param obj An object whose field to get and set
155 155 * @param newValue the new value
156 156 * @return the previous value
157 157 */
158 158 public long getAndSet(T obj, long newValue) {
159 159 for (;;) {
160 160 long current = get(obj);
161 161 if (compareAndSet(obj, current, newValue))
162 162 return current;
163 163 }
164 164 }
165 165
166 166 /**
167 167 * Atomically increments by one the current value of the field of the
168 168 * given object managed by this updater.
169 169 *
170 170 * @param obj An object whose field to get and set
171 171 * @return the previous value
172 172 */
173 173 public long getAndIncrement(T obj) {
174 174 for (;;) {
175 175 long current = get(obj);
176 176 long next = current + 1;
177 177 if (compareAndSet(obj, current, next))
178 178 return current;
179 179 }
180 180 }
181 181
182 182 /**
183 183 * Atomically decrements by one the current value of the field of the
184 184 * given object managed by this updater.
185 185 *
186 186 * @param obj An object whose field to get and set
187 187 * @return the previous value
188 188 */
189 189 public long getAndDecrement(T obj) {
190 190 for (;;) {
191 191 long current = get(obj);
192 192 long next = current - 1;
193 193 if (compareAndSet(obj, current, next))
194 194 return current;
195 195 }
196 196 }
197 197
198 198 /**
199 199 * Atomically adds the given value to the current value of the field of
200 200 * the given object managed by this updater.
201 201 *
202 202 * @param obj An object whose field to get and set
203 203 * @param delta the value to add
204 204 * @return the previous value
205 205 */
206 206 public long getAndAdd(T obj, long delta) {
207 207 for (;;) {
208 208 long current = get(obj);
209 209 long next = current + delta;
210 210 if (compareAndSet(obj, current, next))
211 211 return current;
212 212 }
213 213 }
214 214
215 215 /**
216 216 * Atomically increments by one the current value of the field of the
217 217 * given object managed by this updater.
218 218 *
219 219 * @param obj An object whose field to get and set
220 220 * @return the updated value
221 221 */
222 222 public long incrementAndGet(T obj) {
223 223 for (;;) {
224 224 long current = get(obj);
225 225 long next = current + 1;
226 226 if (compareAndSet(obj, current, next))
227 227 return next;
228 228 }
229 229 }
230 230
231 231 /**
232 232 * Atomically decrements by one the current value of the field of the
233 233 * given object managed by this updater.
234 234 *
235 235 * @param obj An object whose field to get and set
236 236 * @return the updated value
237 237 */
238 238 public long decrementAndGet(T obj) {
239 239 for (;;) {
240 240 long current = get(obj);
241 241 long next = current - 1;
242 242 if (compareAndSet(obj, current, next))
243 243 return next;
244 244 }
245 245 }
246 246
247 247 /**
248 248 * Atomically adds the given value to the current value of the field of
249 249 * the given object managed by this updater.
250 250 *
251 251 * @param obj An object whose field to get and set
252 252 * @param delta the value to add
253 253 * @return the updated value
254 254 */
255 255 public long addAndGet(T obj, long delta) {
256 256 for (;;) {
257 257 long current = get(obj);
258 258 long next = current + delta;
259 259 if (compareAndSet(obj, current, next))
260 260 return next;
261 261 }
262 262 }
263 263
264 264 private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
265 265 private static final Unsafe unsafe = Unsafe.getUnsafe();
266 266 private final long offset;
267 267 private final Class<T> tclass;
268 268 private final Class cclass;
269 269
270 270 CASUpdater(Class<T> tclass, String fieldName) {
↓ open down ↓ |
202 lines elided |
↑ open up ↑ |
271 271 Field field = null;
272 272 Class caller = null;
273 273 int modifiers = 0;
274 274 try {
275 275 field = tclass.getDeclaredField(fieldName);
276 276 caller = sun.reflect.Reflection.getCallerClass(3);
277 277 modifiers = field.getModifiers();
278 278 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
279 279 caller, tclass, null, modifiers);
280 280 sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
281 - } catch(Exception ex) {
281 + } catch (Exception ex) {
282 282 throw new RuntimeException(ex);
283 283 }
284 284
285 285 Class fieldt = field.getType();
286 286 if (fieldt != long.class)
287 287 throw new IllegalArgumentException("Must be long type");
288 288
289 289 if (!Modifier.isVolatile(modifiers))
290 290 throw new IllegalArgumentException("Must be volatile type");
291 291
292 292 this.cclass = (Modifier.isProtected(modifiers) &&
293 293 caller != tclass) ? caller : null;
294 294 this.tclass = tclass;
295 295 offset = unsafe.objectFieldOffset(field);
296 296 }
297 297
298 298 private void fullCheck(T obj) {
299 299 if (!tclass.isInstance(obj))
300 300 throw new ClassCastException();
301 301 if (cclass != null)
302 302 ensureProtectedAccess(obj);
303 303 }
304 304
305 305 public boolean compareAndSet(T obj, long expect, long update) {
306 306 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
307 307 return unsafe.compareAndSwapLong(obj, offset, expect, update);
308 308 }
309 309
310 310 public boolean weakCompareAndSet(T obj, long expect, long update) {
311 311 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
312 312 return unsafe.compareAndSwapLong(obj, offset, expect, update);
313 313 }
314 314
315 315 public void set(T obj, long newValue) {
316 316 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
317 317 unsafe.putLongVolatile(obj, offset, newValue);
318 318 }
319 319
320 320 public void lazySet(T obj, long newValue) {
321 321 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
322 322 unsafe.putOrderedLong(obj, offset, newValue);
323 323 }
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
324 324
325 325 public long get(T obj) {
326 326 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
327 327 return unsafe.getLongVolatile(obj, offset);
328 328 }
329 329
330 330 private void ensureProtectedAccess(T obj) {
331 331 if (cclass.isInstance(obj)) {
332 332 return;
333 333 }
334 - throw new RuntimeException (
334 + throw new RuntimeException(
335 335 new IllegalAccessException("Class " +
336 336 cclass.getName() +
337 337 " can not access a protected member of class " +
338 338 tclass.getName() +
339 339 " using an instance of " +
340 340 obj.getClass().getName()
341 341 )
342 342 );
343 343 }
344 344 }
345 345
346 346
347 347 private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
348 348 private static final Unsafe unsafe = Unsafe.getUnsafe();
349 349 private final long offset;
350 350 private final Class<T> tclass;
351 351 private final Class cclass;
352 352
353 353 LockedUpdater(Class<T> tclass, String fieldName) {
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
354 354 Field field = null;
355 355 Class caller = null;
356 356 int modifiers = 0;
357 357 try {
358 358 field = tclass.getDeclaredField(fieldName);
359 359 caller = sun.reflect.Reflection.getCallerClass(3);
360 360 modifiers = field.getModifiers();
361 361 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
362 362 caller, tclass, null, modifiers);
363 363 sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
364 - } catch(Exception ex) {
364 + } catch (Exception ex) {
365 365 throw new RuntimeException(ex);
366 366 }
367 367
368 368 Class fieldt = field.getType();
369 369 if (fieldt != long.class)
370 370 throw new IllegalArgumentException("Must be long type");
371 371
372 372 if (!Modifier.isVolatile(modifiers))
373 373 throw new IllegalArgumentException("Must be volatile type");
374 374
375 375 this.cclass = (Modifier.isProtected(modifiers) &&
376 376 caller != tclass) ? caller : null;
377 377 this.tclass = tclass;
378 378 offset = unsafe.objectFieldOffset(field);
379 379 }
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
380 380
381 381 private void fullCheck(T obj) {
382 382 if (!tclass.isInstance(obj))
383 383 throw new ClassCastException();
384 384 if (cclass != null)
385 385 ensureProtectedAccess(obj);
386 386 }
387 387
388 388 public boolean compareAndSet(T obj, long expect, long update) {
389 389 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
390 - synchronized(this) {
390 + synchronized (this) {
391 391 long v = unsafe.getLong(obj, offset);
392 392 if (v != expect)
393 393 return false;
394 394 unsafe.putLong(obj, offset, update);
395 395 return true;
396 396 }
397 397 }
398 398
399 399 public boolean weakCompareAndSet(T obj, long expect, long update) {
400 400 return compareAndSet(obj, expect, update);
401 401 }
402 402
403 403 public void set(T obj, long newValue) {
404 404 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
405 - synchronized(this) {
405 + synchronized (this) {
406 406 unsafe.putLong(obj, offset, newValue);
407 407 }
408 408 }
409 409
410 410 public void lazySet(T obj, long newValue) {
411 411 set(obj, newValue);
412 412 }
413 413
414 414 public long get(T obj) {
415 415 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
416 - synchronized(this) {
416 + synchronized (this) {
417 417 return unsafe.getLong(obj, offset);
418 418 }
419 419 }
420 420
421 421 private void ensureProtectedAccess(T obj) {
422 422 if (cclass.isInstance(obj)) {
423 423 return;
424 424 }
425 - throw new RuntimeException (
425 + throw new RuntimeException(
426 426 new IllegalAccessException("Class " +
427 427 cclass.getName() +
428 428 " can not access a protected member of class " +
429 429 tclass.getName() +
430 430 " using an instance of " +
431 431 obj.getClass().getName()
432 432 )
433 433 );
434 434 }
435 435 }
436 436 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX