14 |
|
import java.util.NoSuchElementException; |
15 |
|
import java.util.concurrent.locks.LockSupport; |
16 |
|
import java.util.concurrent.atomic.AtomicReference; |
17 |
– |
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; |
17 |
|
|
18 |
|
/** |
19 |
|
* An unbounded {@linkplain TransferQueue} based on linked nodes. |
114 |
|
this.isData = isData; |
115 |
|
} |
116 |
|
|
118 |
– |
@SuppressWarnings("rawtypes") |
119 |
– |
static final AtomicReferenceFieldUpdater<Node, Node> |
120 |
– |
nextUpdater = AtomicReferenceFieldUpdater.newUpdater |
121 |
– |
(Node.class, Node.class, "next"); |
122 |
– |
|
117 |
|
final boolean casNext(Node<E> cmp, Node<E> val) { |
118 |
< |
return nextUpdater.compareAndSet(this, cmp, val); |
118 |
> |
return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); |
119 |
|
} |
120 |
|
|
121 |
|
final void clearNext() { |
122 |
< |
nextUpdater.lazySet(this, this); |
122 |
> |
UNSAFE.putOrderedObject(this, nextOffset, this); |
123 |
> |
} |
124 |
> |
|
125 |
> |
// Unsafe mechanics |
126 |
> |
|
127 |
> |
private static final sun.misc.Unsafe UNSAFE = getUnsafe(); |
128 |
> |
private static final long nextOffset = |
129 |
> |
objectFieldOffset(UNSAFE, "next", Node.class); |
130 |
> |
|
131 |
> |
/** |
132 |
> |
* Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. |
133 |
> |
* Replace with a simple call to Unsafe.getUnsafe when integrating |
134 |
> |
* into a jdk. |
135 |
> |
* |
136 |
> |
* @return a sun.misc.Unsafe |
137 |
> |
*/ |
138 |
> |
private static sun.misc.Unsafe getUnsafe() { |
139 |
> |
try { |
140 |
> |
return sun.misc.Unsafe.getUnsafe(); |
141 |
> |
} catch (SecurityException se) { |
142 |
> |
try { |
143 |
> |
return java.security.AccessController.doPrivileged |
144 |
> |
(new java.security |
145 |
> |
.PrivilegedExceptionAction<sun.misc.Unsafe>() { |
146 |
> |
public sun.misc.Unsafe run() throws Exception { |
147 |
> |
java.lang.reflect.Field f = sun.misc |
148 |
> |
.Unsafe.class.getDeclaredField("theUnsafe"); |
149 |
> |
f.setAccessible(true); |
150 |
> |
return (sun.misc.Unsafe) f.get(null); |
151 |
> |
}}); |
152 |
> |
} catch (java.security.PrivilegedActionException e) { |
153 |
> |
throw new RuntimeException("Could not initialize intrinsics", |
154 |
> |
e.getCause()); |
155 |
> |
} |
156 |
> |
} |
157 |
|
} |
158 |
|
|
159 |
|
private static final long serialVersionUID = -3375979862319811754L; |
470 |
|
addAll(c); |
471 |
|
} |
472 |
|
|
473 |
+ |
/** |
474 |
+ |
* @throws InterruptedException {@inheritDoc} |
475 |
+ |
* @throws NullPointerException {@inheritDoc} |
476 |
+ |
*/ |
477 |
|
public void put(E e) throws InterruptedException { |
478 |
|
if (e == null) throw new NullPointerException(); |
479 |
|
if (Thread.interrupted()) throw new InterruptedException(); |
480 |
|
xfer(e, NOWAIT, 0); |
481 |
|
} |
482 |
|
|
483 |
+ |
/** |
484 |
+ |
* @throws InterruptedException {@inheritDoc} |
485 |
+ |
* @throws NullPointerException {@inheritDoc} |
486 |
+ |
*/ |
487 |
|
public boolean offer(E e, long timeout, TimeUnit unit) |
488 |
|
throws InterruptedException { |
489 |
|
if (e == null) throw new NullPointerException(); |
492 |
|
return true; |
493 |
|
} |
494 |
|
|
495 |
+ |
/** |
496 |
+ |
* @throws NullPointerException {@inheritDoc} |
497 |
+ |
*/ |
498 |
|
public boolean offer(E e) { |
499 |
|
if (e == null) throw new NullPointerException(); |
500 |
|
xfer(e, NOWAIT, 0); |
501 |
|
return true; |
502 |
|
} |
503 |
|
|
504 |
+ |
/** |
505 |
+ |
* @throws NullPointerException {@inheritDoc} |
506 |
+ |
*/ |
507 |
|
public boolean add(E e) { |
508 |
|
if (e == null) throw new NullPointerException(); |
509 |
|
xfer(e, NOWAIT, 0); |
510 |
|
return true; |
511 |
|
} |
512 |
|
|
513 |
+ |
/** |
514 |
+ |
* @throws InterruptedException {@inheritDoc} |
515 |
+ |
* @throws NullPointerException {@inheritDoc} |
516 |
+ |
*/ |
517 |
|
public void transfer(E e) throws InterruptedException { |
518 |
|
if (e == null) throw new NullPointerException(); |
519 |
|
if (xfer(e, WAIT, 0) == null) { |
522 |
|
} |
523 |
|
} |
524 |
|
|
525 |
+ |
/** |
526 |
+ |
* @throws InterruptedException {@inheritDoc} |
527 |
+ |
* @throws NullPointerException {@inheritDoc} |
528 |
+ |
*/ |
529 |
|
public boolean tryTransfer(E e, long timeout, TimeUnit unit) |
530 |
|
throws InterruptedException { |
531 |
|
if (e == null) throw new NullPointerException(); |
536 |
|
throw new InterruptedException(); |
537 |
|
} |
538 |
|
|
539 |
+ |
/** |
540 |
+ |
* @throws NullPointerException {@inheritDoc} |
541 |
+ |
*/ |
542 |
|
public boolean tryTransfer(E e) { |
543 |
|
if (e == null) throw new NullPointerException(); |
544 |
|
return fulfill(e) != null; |
545 |
|
} |
546 |
|
|
547 |
+ |
/** |
548 |
+ |
* @throws InterruptedException {@inheritDoc} |
549 |
+ |
*/ |
550 |
|
public E take() throws InterruptedException { |
551 |
|
Object e = xfer(null, WAIT, 0); |
552 |
|
if (e != null) |
555 |
|
throw new InterruptedException(); |
556 |
|
} |
557 |
|
|
558 |
+ |
/** |
559 |
+ |
* @throws InterruptedException {@inheritDoc} |
560 |
+ |
*/ |
561 |
|
public E poll(long timeout, TimeUnit unit) throws InterruptedException { |
562 |
|
Object e = xfer(null, TIMEOUT, unit.toNanos(timeout)); |
563 |
|
if (e != null || !Thread.interrupted()) |
569 |
|
return fulfill(null); |
570 |
|
} |
571 |
|
|
572 |
+ |
/** |
573 |
+ |
* @throws NullPointerException {@inheritDoc} |
574 |
+ |
* @throws IllegalArgumentException {@inheritDoc} |
575 |
+ |
*/ |
576 |
|
public int drainTo(Collection<? super E> c) { |
577 |
|
if (c == null) |
578 |
|
throw new NullPointerException(); |
587 |
|
return n; |
588 |
|
} |
589 |
|
|
590 |
+ |
/** |
591 |
+ |
* @throws NullPointerException {@inheritDoc} |
592 |
+ |
* @throws IllegalArgumentException {@inheritDoc} |
593 |
+ |
*/ |
594 |
|
public int drainTo(Collection<? super E> c, int maxElements) { |
595 |
|
if (c == null) |
596 |
|
throw new NullPointerException(); |
866 |
|
new PaddedAtomicReference<Node<E>>(null)); |
867 |
|
} |
868 |
|
|
869 |
< |
// Unsafe mechanics for jsr166y 3rd party package. |
869 |
> |
// Unsafe mechanics |
870 |
> |
|
871 |
> |
private static final sun.misc.Unsafe UNSAFE = getUnsafe(); |
872 |
> |
private static final long headOffset = |
873 |
> |
objectFieldOffset(UNSAFE, "head", LinkedTransferQueue.class); |
874 |
> |
private static final long tailOffset = |
875 |
> |
objectFieldOffset(UNSAFE, "tail", LinkedTransferQueue.class); |
876 |
> |
private static final long cleanMeOffset = |
877 |
> |
objectFieldOffset(UNSAFE, "cleanMe", LinkedTransferQueue.class); |
878 |
> |
|
879 |
> |
|
880 |
> |
static long objectFieldOffset(sun.misc.Unsafe UNSAFE, |
881 |
> |
String field, Class<?> klazz) { |
882 |
> |
try { |
883 |
> |
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); |
884 |
> |
} catch (NoSuchFieldException e) { |
885 |
> |
// Convert Exception to corresponding Error |
886 |
> |
NoSuchFieldError error = new NoSuchFieldError(field); |
887 |
> |
error.initCause(e); |
888 |
> |
throw error; |
889 |
> |
} |
890 |
> |
} |
891 |
> |
|
892 |
> |
/** |
893 |
> |
* Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. |
894 |
> |
* Replace with a simple call to Unsafe.getUnsafe when integrating |
895 |
> |
* into a jdk. |
896 |
> |
* |
897 |
> |
* @return a sun.misc.Unsafe |
898 |
> |
*/ |
899 |
|
private static sun.misc.Unsafe getUnsafe() { |
900 |
|
try { |
901 |
|
return sun.misc.Unsafe.getUnsafe(); |
902 |
|
} catch (SecurityException se) { |
903 |
|
try { |
904 |
|
return java.security.AccessController.doPrivileged |
905 |
< |
(new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() { |
905 |
> |
(new java.security |
906 |
> |
.PrivilegedExceptionAction<sun.misc.Unsafe>() { |
907 |
|
public sun.misc.Unsafe run() throws Exception { |
908 |
< |
return getUnsafeByReflection(); |
908 |
> |
java.lang.reflect.Field f = sun.misc |
909 |
> |
.Unsafe.class.getDeclaredField("theUnsafe"); |
910 |
> |
f.setAccessible(true); |
911 |
> |
return (sun.misc.Unsafe) f.get(null); |
912 |
|
}}); |
913 |
|
} catch (java.security.PrivilegedActionException e) { |
914 |
|
throw new RuntimeException("Could not initialize intrinsics", |
916 |
|
} |
917 |
|
} |
918 |
|
} |
819 |
– |
|
820 |
– |
private static sun.misc.Unsafe getUnsafeByReflection() |
821 |
– |
throws NoSuchFieldException, IllegalAccessException { |
822 |
– |
java.lang.reflect.Field f = |
823 |
– |
sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); |
824 |
– |
f.setAccessible(true); |
825 |
– |
return (sun.misc.Unsafe) f.get(null); |
826 |
– |
} |
827 |
– |
|
828 |
– |
private static long fieldOffset(String fieldName, Class<?> klazz) { |
829 |
– |
try { |
830 |
– |
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(fieldName)); |
831 |
– |
} catch (NoSuchFieldException e) { |
832 |
– |
// Convert Exception to Error |
833 |
– |
NoSuchFieldError error = new NoSuchFieldError(fieldName); |
834 |
– |
error.initCause(e); |
835 |
– |
throw error; |
836 |
– |
} |
837 |
– |
} |
838 |
– |
|
839 |
– |
private static final sun.misc.Unsafe UNSAFE = getUnsafe(); |
840 |
– |
static final long headOffset = |
841 |
– |
fieldOffset("head", LinkedTransferQueue.class); |
842 |
– |
static final long tailOffset = |
843 |
– |
fieldOffset("tail", LinkedTransferQueue.class); |
844 |
– |
static final long cleanMeOffset = |
845 |
– |
fieldOffset("cleanMe", LinkedTransferQueue.class); |
846 |
– |
|
919 |
|
} |