src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java

Print this page




  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * Written by Doug Lea with assistance from members of JCP JSR-166
  32  * Expert Group and released to the public domain, as explained at
  33  * http://creativecommons.org/licenses/publicdomain
  34  */
  35 
  36 package java.util.concurrent.atomic;
  37 import sun.misc.Unsafe;
  38 import java.lang.reflect.*;
  39 
  40 /**
  41  * A reflection-based utility that enables atomic updates to
  42  * designated {@code volatile} reference fields of designated
  43  * classes.  This class is designed for use in atomic data structures
  44  * in which several reference fields of the same node are
  45  * independently subject to atomic updates. For example, a tree node
  46  * might be declared as
  47  *
  48  * <pre>
  49  * class Node {
  50  *   private volatile Node left, right;
  51  *
  52  *   private static final AtomicReferenceFieldUpdater&lt;Node, Node&gt; leftUpdater =
  53  *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
  54  *   private static AtomicReferenceFieldUpdater&lt;Node, Node&gt; rightUpdater =
  55  *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
  56  *
  57  *   Node getLeft() { return left;  }
  58  *   boolean compareAndSetLeft(Node expect, Node update) {
  59  *     return leftUpdater.compareAndSet(this, expect, update);
  60  *   }
  61  *   // ... and so on
  62  * }
  63  * </pre>
  64  *
  65  * <p>Note that the guarantees of the {@code compareAndSet}
  66  * method in this class are weaker than in other atomic classes.
  67  * Because this class cannot ensure that all uses of the field
  68  * are appropriate for purposes of atomic access, it can
  69  * guarantee atomicity only with respect to other invocations of
  70  * {@code compareAndSet} and {@code set} on the same updater.
  71  *
  72  * @since 1.5
  73  * @author Doug Lea
  74  * @param <T> The type of the object holding the updatable field
  75  * @param <V> The type of the field
  76  */
  77 public abstract class AtomicReferenceFieldUpdater<T, V>  {
  78 
  79     /**
  80      * Creates and returns an updater for objects with the given field.
  81      * The Class arguments are needed to check that reflective types and
  82      * generic types match.
  83      *


 274         }
 275 
 276         public void lazySet(T obj, V newValue) {
 277             if (obj == null || obj.getClass() != tclass || cclass != null ||
 278                 (newValue != null && vclass != null &&
 279                  vclass != newValue.getClass()))
 280                 updateCheck(obj, newValue);
 281             unsafe.putOrderedObject(obj, offset, newValue);
 282         }
 283 
 284         public V get(T obj) {
 285             if (obj == null || obj.getClass() != tclass || cclass != null)
 286                 targetCheck(obj);
 287             return (V)unsafe.getObjectVolatile(obj, offset);
 288         }
 289 
 290         private void ensureProtectedAccess(T obj) {
 291             if (cclass.isInstance(obj)) {
 292                 return;
 293             }
 294             throw new RuntimeException (
 295                 new IllegalAccessException("Class " +
 296                     cclass.getName() +
 297                     " can not access a protected member of class " +
 298                     tclass.getName() +
 299                     " using an instance of " +
 300                     obj.getClass().getName()
 301                 )
 302             );
 303         }
 304     }
 305 }


  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * Written by Doug Lea with assistance from members of JCP JSR-166
  32  * Expert Group and released to the public domain, as explained at
  33  * http://creativecommons.org/licenses/publicdomain
  34  */
  35 
  36 package java.util.concurrent.atomic;
  37 import sun.misc.Unsafe;
  38 import java.lang.reflect.*;
  39 
  40 /**
  41  * A reflection-based utility that enables atomic updates to
  42  * designated {@code volatile} reference fields of designated
  43  * classes.  This class is designed for use in atomic data structures
  44  * in which several reference fields of the same node are
  45  * independently subject to atomic updates. For example, a tree node
  46  * might be declared as
  47  *
  48  *  <pre> {@code
  49  * class Node {
  50  *   private volatile Node left, right;
  51  *
  52  *   private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
  53  *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
  54  *   private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
  55  *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
  56  *
  57  *   Node getLeft() { return left;  }
  58  *   boolean compareAndSetLeft(Node expect, Node update) {
  59  *     return leftUpdater.compareAndSet(this, expect, update);
  60  *   }
  61  *   // ... and so on
  62  * }}</pre>

  63  *
  64  * <p>Note that the guarantees of the {@code compareAndSet}
  65  * method in this class are weaker than in other atomic classes.
  66  * Because this class cannot ensure that all uses of the field
  67  * are appropriate for purposes of atomic access, it can
  68  * guarantee atomicity only with respect to other invocations of
  69  * {@code compareAndSet} and {@code set} on the same updater.
  70  *
  71  * @since 1.5
  72  * @author Doug Lea
  73  * @param <T> The type of the object holding the updatable field
  74  * @param <V> The type of the field
  75  */
  76 public abstract class AtomicReferenceFieldUpdater<T, V> {
  77 
  78     /**
  79      * Creates and returns an updater for objects with the given field.
  80      * The Class arguments are needed to check that reflective types and
  81      * generic types match.
  82      *


 273         }
 274 
 275         public void lazySet(T obj, V newValue) {
 276             if (obj == null || obj.getClass() != tclass || cclass != null ||
 277                 (newValue != null && vclass != null &&
 278                  vclass != newValue.getClass()))
 279                 updateCheck(obj, newValue);
 280             unsafe.putOrderedObject(obj, offset, newValue);
 281         }
 282 
 283         public V get(T obj) {
 284             if (obj == null || obj.getClass() != tclass || cclass != null)
 285                 targetCheck(obj);
 286             return (V)unsafe.getObjectVolatile(obj, offset);
 287         }
 288 
 289         private void ensureProtectedAccess(T obj) {
 290             if (cclass.isInstance(obj)) {
 291                 return;
 292             }
 293             throw new RuntimeException(
 294                 new IllegalAccessException("Class " +
 295                     cclass.getName() +
 296                     " can not access a protected member of class " +
 297                     tclass.getName() +
 298                     " using an instance of " +
 299                     obj.getClass().getName()
 300                 )
 301             );
 302         }
 303     }
 304 }