363 } |
363 } |
364 |
364 |
365 /** |
365 /** |
366 * Standard hotspot implementation using intrinsics. |
366 * Standard hotspot implementation using intrinsics. |
367 */ |
367 */ |
368 private static class AtomicIntegerFieldUpdaterImpl<T> |
368 private static final class AtomicIntegerFieldUpdaterImpl<T> |
369 extends AtomicIntegerFieldUpdater<T> { |
369 extends AtomicIntegerFieldUpdater<T> { |
370 private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); |
370 private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); |
371 private final long offset; |
371 private final long offset; |
|
372 /** |
|
373 * if field is protected, the subclass constructing updater, else |
|
374 * the same as tclass |
|
375 */ |
|
376 private final Class<?> cclass; |
|
377 /** class holding the field */ |
372 private final Class<T> tclass; |
378 private final Class<T> tclass; |
373 private final Class<?> cclass; |
|
374 |
379 |
375 AtomicIntegerFieldUpdaterImpl(final Class<T> tclass, |
380 AtomicIntegerFieldUpdaterImpl(final Class<T> tclass, |
376 final String fieldName, |
381 final String fieldName, |
377 final Class<?> caller) { |
382 final Class<?> caller) { |
378 final Field field; |
383 final Field field; |
397 throw new RuntimeException(pae.getException()); |
402 throw new RuntimeException(pae.getException()); |
398 } catch (Exception ex) { |
403 } catch (Exception ex) { |
399 throw new RuntimeException(ex); |
404 throw new RuntimeException(ex); |
400 } |
405 } |
401 |
406 |
402 Class<?> fieldt = field.getType(); |
407 if (field.getType() != int.class) |
403 if (fieldt != int.class) |
|
404 throw new IllegalArgumentException("Must be integer type"); |
408 throw new IllegalArgumentException("Must be integer type"); |
405 |
409 |
406 if (!Modifier.isVolatile(modifiers)) |
410 if (!Modifier.isVolatile(modifiers)) |
407 throw new IllegalArgumentException("Must be volatile type"); |
411 throw new IllegalArgumentException("Must be volatile type"); |
408 |
412 |
409 this.cclass = (Modifier.isProtected(modifiers) && |
413 this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass; |
410 caller != tclass) ? caller : null; |
|
411 this.tclass = tclass; |
414 this.tclass = tclass; |
412 offset = U.objectFieldOffset(field); |
415 this.offset = U.objectFieldOffset(field); |
413 } |
416 } |
414 |
417 |
415 /** |
418 /** |
416 * Returns true if the second classloader can be found in the first |
419 * Returns true if the second classloader can be found in the first |
417 * classloader's delegation chain. |
420 * classloader's delegation chain. |
426 } |
429 } |
427 } while (acl != null); |
430 } while (acl != null); |
428 return false; |
431 return false; |
429 } |
432 } |
430 |
433 |
431 private void fullCheck(T obj) { |
434 /** |
432 if (!tclass.isInstance(obj)) |
435 * Checks that target argument is instance of cclass. On |
|
436 * failure, throws cause. |
|
437 */ |
|
438 private final void accessCheck(T obj) { |
|
439 if (!cclass.isInstance(obj)) |
|
440 throwAccessCheckException(obj); |
|
441 } |
|
442 |
|
443 /** |
|
444 * Throws access exception if accessCheck failed due to |
|
445 * protected access, else ClassCastException. |
|
446 */ |
|
447 private final void throwAccessCheckException(T obj) { |
|
448 if (cclass == tclass) |
433 throw new ClassCastException(); |
449 throw new ClassCastException(); |
434 if (cclass != null) |
450 else |
435 ensureProtectedAccess(obj); |
451 throw new RuntimeException( |
436 } |
452 new IllegalAccessException( |
437 |
453 "Class " + |
438 public boolean compareAndSet(T obj, int expect, int update) { |
454 cclass.getName() + |
439 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); |
455 " can not access a protected member of class " + |
|
456 tclass.getName() + |
|
457 " using an instance of " + |
|
458 obj.getClass().getName())); |
|
459 } |
|
460 |
|
461 public final boolean compareAndSet(T obj, int expect, int update) { |
|
462 accessCheck(obj); |
440 return U.compareAndSwapInt(obj, offset, expect, update); |
463 return U.compareAndSwapInt(obj, offset, expect, update); |
441 } |
464 } |
442 |
465 |
443 public boolean weakCompareAndSet(T obj, int expect, int update) { |
466 public final boolean weakCompareAndSet(T obj, int expect, int update) { |
444 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); |
467 accessCheck(obj); |
445 return U.compareAndSwapInt(obj, offset, expect, update); |
468 return U.compareAndSwapInt(obj, offset, expect, update); |
446 } |
469 } |
447 |
470 |
448 public void set(T obj, int newValue) { |
471 public final void set(T obj, int newValue) { |
449 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); |
472 accessCheck(obj); |
450 U.putIntVolatile(obj, offset, newValue); |
473 U.putIntVolatile(obj, offset, newValue); |
451 } |
474 } |
452 |
475 |
453 public void lazySet(T obj, int newValue) { |
476 public final void lazySet(T obj, int newValue) { |
454 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); |
477 accessCheck(obj); |
455 U.putOrderedInt(obj, offset, newValue); |
478 U.putOrderedInt(obj, offset, newValue); |
456 } |
479 } |
457 |
480 |
458 public final int get(T obj) { |
481 public final int get(T obj) { |
459 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); |
482 accessCheck(obj); |
460 return U.getIntVolatile(obj, offset); |
483 return U.getIntVolatile(obj, offset); |
461 } |
484 } |
462 |
485 |
463 public int getAndSet(T obj, int newValue) { |
486 public final int getAndSet(T obj, int newValue) { |
464 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); |
487 accessCheck(obj); |
465 return U.getAndSetInt(obj, offset, newValue); |
488 return U.getAndSetInt(obj, offset, newValue); |
466 } |
489 } |
467 |
490 |
468 public int getAndIncrement(T obj) { |
491 public final int getAndAdd(T obj, int delta) { |
|
492 accessCheck(obj); |
|
493 return U.getAndAddInt(obj, offset, delta); |
|
494 } |
|
495 |
|
496 public final int getAndIncrement(T obj) { |
469 return getAndAdd(obj, 1); |
497 return getAndAdd(obj, 1); |
470 } |
498 } |
471 |
499 |
472 public int getAndDecrement(T obj) { |
500 public final int getAndDecrement(T obj) { |
473 return getAndAdd(obj, -1); |
501 return getAndAdd(obj, -1); |
474 } |
502 } |
475 |
503 |
476 public int getAndAdd(T obj, int delta) { |
504 public final int incrementAndGet(T obj) { |
477 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); |
|
478 return U.getAndAddInt(obj, offset, delta); |
|
479 } |
|
480 |
|
481 public int incrementAndGet(T obj) { |
|
482 return getAndAdd(obj, 1) + 1; |
505 return getAndAdd(obj, 1) + 1; |
483 } |
506 } |
484 |
507 |
485 public int decrementAndGet(T obj) { |
508 public final int decrementAndGet(T obj) { |
486 return getAndAdd(obj, -1) - 1; |
509 return getAndAdd(obj, -1) - 1; |
487 } |
510 } |
488 |
511 |
489 public int addAndGet(T obj, int delta) { |
512 public final int addAndGet(T obj, int delta) { |
490 return getAndAdd(obj, delta) + delta; |
513 return getAndAdd(obj, delta) + delta; |
491 } |
514 } |
492 |
515 |
493 private void ensureProtectedAccess(T obj) { |
|
494 if (cclass.isInstance(obj)) { |
|
495 return; |
|
496 } |
|
497 throw new RuntimeException( |
|
498 new IllegalAccessException("Class " + |
|
499 cclass.getName() + |
|
500 " can not access a protected member of class " + |
|
501 tclass.getName() + |
|
502 " using an instance of " + |
|
503 obj.getClass().getName() |
|
504 ) |
|
505 ); |
|
506 } |
|
507 } |
516 } |
508 } |
517 } |