summaryrefslogtreecommitdiff
path: root/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java')
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java275
1 files changed, 275 insertions, 0 deletions
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
new file mode 100644
index 000000000..24014a9df
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -0,0 +1,275 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.atomic;
+import sun.misc.Unsafe;
+import java.lang.reflect.*;
+
+/**
+ * A reflection-based utility that enables atomic updates to
+ * designated <tt>volatile</tt> reference fields of designated
+ * classes. This class is designed for use in atomic data structures
+ * in which several reference fields of the same node are
+ * independently subject to atomic updates. For example, a tree node
+ * might be declared as
+ *
+ * <pre>
+ * class Node {
+ * private volatile Node left, right;
+ *
+ * private static final AtomicReferenceFieldUpdater&lt;Node, Node&gt; leftUpdater =
+ * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
+ * private static AtomicReferenceFieldUpdater&lt;Node, Node&gt; rightUpdater =
+ * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
+ *
+ * Node getLeft() { return left; }
+ * boolean compareAndSetLeft(Node expect, Node update) {
+ * return leftUpdater.compareAndSet(this, expect, update);
+ * }
+ * // ... and so on
+ * }
+ * </pre>
+ *
+ * <p>Note that the guarantees of the {@code compareAndSet}
+ * method in this class are weaker than in other atomic classes.
+ * Because this class cannot ensure that all uses of the field
+ * are appropriate for purposes of atomic access, it can
+ * guarantee atomicity only with respect to other invocations of
+ * {@code compareAndSet} and {@code set} on the same updater.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <T> The type of the object holding the updatable field
+ * @param <V> The type of the field
+ */
+public abstract class AtomicReferenceFieldUpdater<T, V> {
+
+ /**
+ * Creates and returns an updater for objects with the given field.
+ * The Class arguments are needed to check that reflective types and
+ * generic types match.
+ *
+ * @param tclass the class of the objects holding the field.
+ * @param vclass the class of the field
+ * @param fieldName the name of the field to be updated.
+ * @return the updater
+ * @throws IllegalArgumentException if the field is not a volatile reference type.
+ * @throws RuntimeException with a nested reflection-based
+ * exception if the class does not hold field or is the wrong type.
+ */
+ public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
+ return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
+ vclass,
+ fieldName);
+ }
+
+ /**
+ * Protected do-nothing constructor for use by subclasses.
+ */
+ protected AtomicReferenceFieldUpdater() {
+ }
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public abstract boolean compareAndSet(T obj, V expect, V update);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public abstract boolean weakCompareAndSet(T obj, V expect, V update);
+
+ /**
+ * Sets the field of the given object managed by this updater to the
+ * given updated value. This operation is guaranteed to act as a volatile
+ * store with respect to subsequent invocations of
+ * <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ */
+ public abstract void set(T obj, V newValue);
+
+ /**
+ * Eventually sets the field of the given object managed by this
+ * updater to the given updated value.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public abstract void lazySet(T obj, V newValue);
+
+ /**
+ * Gets the current value held in the field of the given object managed
+ * by this updater.
+ *
+ * @param obj An object whose field to get
+ * @return the current value
+ */
+ public abstract V get(T obj);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given value and returns the old value.
+ *
+ * @param obj An object whose field to get and set
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public V getAndSet(T obj, V newValue) {
+ for (;;) {
+ V current = get(obj);
+ if (compareAndSet(obj, current, newValue))
+ return current;
+ }
+ }
+
+ private static final class AtomicReferenceFieldUpdaterImpl<T,V>
+ extends AtomicReferenceFieldUpdater<T,V> {
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private final long offset;
+ private final Class<T> tclass;
+ private final Class<V> vclass;
+ private final Class cclass;
+
+ /*
+ * Internal type checks within all update methods contain
+ * internal inlined optimizations checking for the common
+ * cases where the class is final (in which case a simple
+ * getClass comparison suffices) or is of type Object (in
+ * which case no check is needed because all objects are
+ * instances of Object). The Object case is handled simply by
+ * setting vclass to null in constructor. The targetCheck and
+ * updateCheck methods are invoked when these faster
+ * screenings fail.
+ */
+
+ AtomicReferenceFieldUpdaterImpl(Class<T> tclass,
+ Class<V> vclass,
+ String fieldName) {
+ Field field = null;
+ Class fieldClass = null;
+ Class caller = null;
+ int modifiers = 0;
+ try {
+ field = tclass.getDeclaredField(fieldName);
+ caller = sun.reflect.Reflection.getCallerClass(3);
+ modifiers = field.getModifiers();
+ sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ caller, tclass, null, modifiers);
+ sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ fieldClass = field.getType();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ if (vclass != fieldClass)
+ throw new ClassCastException();
+
+ if (!Modifier.isVolatile(modifiers))
+ throw new IllegalArgumentException("Must be volatile type");
+
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ caller != tclass) ? caller : null;
+ this.tclass = tclass;
+ if (vclass == Object.class)
+ this.vclass = null;
+ else
+ this.vclass = vclass;
+ offset = unsafe.objectFieldOffset(field);
+ }
+
+ void targetCheck(T obj) {
+ if (!tclass.isInstance(obj))
+ throw new ClassCastException();
+ if (cclass != null)
+ ensureProtectedAccess(obj);
+ }
+
+ void updateCheck(T obj, V update) {
+ if (!tclass.isInstance(obj) ||
+ (update != null && vclass != null && !vclass.isInstance(update)))
+ throw new ClassCastException();
+ if (cclass != null)
+ ensureProtectedAccess(obj);
+ }
+
+ public boolean compareAndSet(T obj, V expect, V update) {
+ if (obj == null || obj.getClass() != tclass || cclass != null ||
+ (update != null && vclass != null &&
+ vclass != update.getClass()))
+ updateCheck(obj, update);
+ return unsafe.compareAndSwapObject(obj, offset, expect, update);
+ }
+
+ public boolean weakCompareAndSet(T obj, V expect, V update) {
+ // same implementation as strong form for now
+ if (obj == null || obj.getClass() != tclass || cclass != null ||
+ (update != null && vclass != null &&
+ vclass != update.getClass()))
+ updateCheck(obj, update);
+ return unsafe.compareAndSwapObject(obj, offset, expect, update);
+ }
+
+ public void set(T obj, V newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null ||
+ (newValue != null && vclass != null &&
+ vclass != newValue.getClass()))
+ updateCheck(obj, newValue);
+ unsafe.putObjectVolatile(obj, offset, newValue);
+ }
+
+ public void lazySet(T obj, V newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null ||
+ (newValue != null && vclass != null &&
+ vclass != newValue.getClass()))
+ updateCheck(obj, newValue);
+ unsafe.putOrderedObject(obj, offset, newValue);
+ }
+
+ public V get(T obj) {
+ if (obj == null || obj.getClass() != tclass || cclass != null)
+ targetCheck(obj);
+ return (V)unsafe.getObjectVolatile(obj, offset);
+ }
+
+ private void ensureProtectedAccess(T obj) {
+ if (cclass.isInstance(obj)) {
+ return;
+ }
+ throw new RuntimeException (
+ new IllegalAccessException("Class " +
+ cclass.getName() +
+ " can not access a protected member of class " +
+ tclass.getName() +
+ " using an instance of " +
+ obj.getClass().getName()
+ )
+ );
+ }
+ }
+}