--- jsr166/src/jsr166y/LinkedTransferQueue.java 2009/07/26 17:33:37 1.28 +++ jsr166/src/jsr166y/LinkedTransferQueue.java 2009/07/29 02:19:56 1.32 @@ -14,7 +14,6 @@ import java.util.Iterator; import java.util.NoSuchElementException; import java.util.concurrent.locks.LockSupport; import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; /** * An unbounded {@linkplain TransferQueue} based on linked nodes. @@ -115,17 +114,46 @@ public class LinkedTransferQueue exte this.isData = isData; } - @SuppressWarnings("rawtypes") - static final AtomicReferenceFieldUpdater - nextUpdater = AtomicReferenceFieldUpdater.newUpdater - (Node.class, Node.class, "next"); + // Unsafe mechanics + + private static final sun.misc.Unsafe UNSAFE = getUnsafe(); + private static final long nextOffset = + objectFieldOffset(UNSAFE, "next", Node.class); final boolean casNext(Node cmp, Node val) { - return nextUpdater.compareAndSet(this, cmp, val); + return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); } final void clearNext() { - nextUpdater.lazySet(this, this); + UNSAFE.putOrderedObject(this, nextOffset, this); + } + + /** + * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. + * Replace with a simple call to Unsafe.getUnsafe when integrating + * into a jdk. + * + * @return a sun.misc.Unsafe + */ + private static sun.misc.Unsafe getUnsafe() { + try { + return sun.misc.Unsafe.getUnsafe(); + } catch (SecurityException se) { + try { + return java.security.AccessController.doPrivileged + (new java.security + .PrivilegedExceptionAction() { + public sun.misc.Unsafe run() throws Exception { + java.lang.reflect.Field f = sun.misc + .Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + return (sun.misc.Unsafe) f.get(null); + }}); + } catch (java.security.PrivilegedActionException e) { + throw new RuntimeException("Could not initialize intrinsics", + e.getCause()); + } + } } private static final long serialVersionUID = -3375979862319811754L; @@ -442,12 +470,20 @@ public class LinkedTransferQueue exte addAll(c); } + /** + * @throws InterruptedException {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + */ public void put(E e) throws InterruptedException { if (e == null) throw new NullPointerException(); if (Thread.interrupted()) throw new InterruptedException(); xfer(e, NOWAIT, 0); } + /** + * @throws InterruptedException {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + */ public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException { if (e == null) throw new NullPointerException(); @@ -456,18 +492,28 @@ public class LinkedTransferQueue exte return true; } + /** + * @throws NullPointerException {@inheritDoc} + */ public boolean offer(E e) { if (e == null) throw new NullPointerException(); xfer(e, NOWAIT, 0); return true; } + /** + * @throws NullPointerException {@inheritDoc} + */ public boolean add(E e) { if (e == null) throw new NullPointerException(); xfer(e, NOWAIT, 0); return true; } + /** + * @throws InterruptedException {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + */ public void transfer(E e) throws InterruptedException { if (e == null) throw new NullPointerException(); if (xfer(e, WAIT, 0) == null) { @@ -476,6 +522,10 @@ public class LinkedTransferQueue exte } } + /** + * @throws InterruptedException {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + */ public boolean tryTransfer(E e, long timeout, TimeUnit unit) throws InterruptedException { if (e == null) throw new NullPointerException(); @@ -486,11 +536,17 @@ public class LinkedTransferQueue exte throw new InterruptedException(); } + /** + * @throws NullPointerException {@inheritDoc} + */ public boolean tryTransfer(E e) { if (e == null) throw new NullPointerException(); return fulfill(e) != null; } + /** + * @throws InterruptedException {@inheritDoc} + */ public E take() throws InterruptedException { Object e = xfer(null, WAIT, 0); if (e != null) @@ -499,6 +555,9 @@ public class LinkedTransferQueue exte throw new InterruptedException(); } + /** + * @throws InterruptedException {@inheritDoc} + */ public E poll(long timeout, TimeUnit unit) throws InterruptedException { Object e = xfer(null, TIMEOUT, unit.toNanos(timeout)); if (e != null || !Thread.interrupted()) @@ -510,6 +569,10 @@ public class LinkedTransferQueue exte return fulfill(null); } + /** + * @throws NullPointerException {@inheritDoc} + * @throws IllegalArgumentException {@inheritDoc} + */ public int drainTo(Collection c) { if (c == null) throw new NullPointerException(); @@ -524,6 +587,10 @@ public class LinkedTransferQueue exte return n; } + /** + * @throws NullPointerException {@inheritDoc} + * @throws IllegalArgumentException {@inheritDoc} + */ public int drainTo(Collection c, int maxElements) { if (c == null) throw new NullPointerException(); @@ -803,13 +870,15 @@ public class LinkedTransferQueue exte private static final sun.misc.Unsafe UNSAFE = getUnsafe(); private static final long headOffset = - objectFieldOffset("head", LinkedTransferQueue.class); + objectFieldOffset(UNSAFE, "head", LinkedTransferQueue.class); private static final long tailOffset = - objectFieldOffset("tail", LinkedTransferQueue.class); + objectFieldOffset(UNSAFE, "tail", LinkedTransferQueue.class); private static final long cleanMeOffset = - objectFieldOffset("cleanMe", LinkedTransferQueue.class); + objectFieldOffset(UNSAFE, "cleanMe", LinkedTransferQueue.class); + - private static long objectFieldOffset(String field, Class klazz) { + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, + String field, Class klazz) { try { return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); } catch (NoSuchFieldException e) {