jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
changeset 34339 61d78c23fcdc
parent 33674 566777f73c32
child 36936 bfcdf736a998
equal deleted inserted replaced
34338:67d0e5867568 34339:61d78c23fcdc
   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 }