diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java | |
download | cbb-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.java | 275 |
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<Node, Node> leftUpdater = + * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left"); + * private static AtomicReferenceFieldUpdater<Node, Node> 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() + ) + ); + } + } +} |