6 |
|
|
7 |
|
package java.util.concurrent; |
8 |
|
|
9 |
+ |
import java.lang.invoke.MethodHandles; |
10 |
+ |
import java.lang.invoke.VarHandle; |
11 |
|
import java.util.AbstractQueue; |
12 |
|
import java.util.Arrays; |
13 |
|
import java.util.Collection; |
417 |
|
|
418 |
|
/** |
419 |
|
* Queue nodes. Uses Object, not E, for items to allow forgetting |
420 |
< |
* them after use. Relies heavily on Unsafe mechanics to minimize |
420 |
> |
* them after use. Relies heavily on VarHandles to minimize |
421 |
|
* unnecessary ordering constraints: Writes that are intrinsically |
422 |
|
* ordered wrt other accesses or CASes use simple relaxed forms. |
423 |
|
*/ |
429 |
|
|
430 |
|
// CAS methods for fields |
431 |
|
final boolean casNext(Node cmp, Node val) { |
432 |
< |
return U.compareAndSwapObject(this, NEXT, cmp, val); |
432 |
> |
return NEXT.compareAndSet(this, cmp, val); |
433 |
|
} |
434 |
|
|
435 |
|
final boolean casItem(Object cmp, Object val) { |
436 |
|
// assert cmp == null || cmp.getClass() != Node.class; |
437 |
< |
return U.compareAndSwapObject(this, ITEM, cmp, val); |
437 |
> |
return ITEM.compareAndSet(this, cmp, val); |
438 |
|
} |
439 |
|
|
440 |
|
/** |
442 |
|
* only be seen after publication via casNext. |
443 |
|
*/ |
444 |
|
Node(Object item, boolean isData) { |
445 |
< |
U.putObject(this, ITEM, item); // relaxed write |
445 |
> |
ITEM.set(this, item); // relaxed write |
446 |
|
this.isData = isData; |
447 |
|
} |
448 |
|
|
451 |
|
* only after CASing head field, so uses relaxed write. |
452 |
|
*/ |
453 |
|
final void forgetNext() { |
454 |
< |
U.putObject(this, NEXT, this); |
454 |
> |
NEXT.set(this, this); |
455 |
|
} |
456 |
|
|
457 |
|
/** |
464 |
|
* else we don't care). |
465 |
|
*/ |
466 |
|
final void forgetContents() { |
467 |
< |
U.putObject(this, ITEM, this); |
468 |
< |
U.putObject(this, WAITER, null); |
467 |
> |
ITEM.set(this, this); |
468 |
> |
WAITER.set(this, null); |
469 |
|
} |
470 |
|
|
471 |
|
/** |
510 |
|
|
511 |
|
private static final long serialVersionUID = -3375979862319811754L; |
512 |
|
|
513 |
< |
// Unsafe mechanics |
514 |
< |
private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); |
515 |
< |
private static final long ITEM; |
516 |
< |
private static final long NEXT; |
515 |
< |
private static final long WAITER; |
513 |
> |
// VarHandle mechanics |
514 |
> |
private static final VarHandle ITEM; |
515 |
> |
private static final VarHandle NEXT; |
516 |
> |
private static final VarHandle WAITER; |
517 |
|
static { |
518 |
|
try { |
519 |
< |
ITEM = U.objectFieldOffset |
520 |
< |
(Node.class.getDeclaredField("item")); |
521 |
< |
NEXT = U.objectFieldOffset |
522 |
< |
(Node.class.getDeclaredField("next")); |
522 |
< |
WAITER = U.objectFieldOffset |
523 |
< |
(Node.class.getDeclaredField("waiter")); |
519 |
> |
MethodHandles.Lookup l = MethodHandles.lookup(); |
520 |
> |
ITEM = l.findVarHandle(Node.class, "item", Object.class); |
521 |
> |
NEXT = l.findVarHandle(Node.class, "next", Node.class); |
522 |
> |
WAITER = l.findVarHandle(Node.class, "waiter", Thread.class); |
523 |
|
} catch (ReflectiveOperationException e) { |
524 |
|
throw new Error(e); |
525 |
|
} |
537 |
|
|
538 |
|
// CAS methods for fields |
539 |
|
private boolean casTail(Node cmp, Node val) { |
540 |
< |
return U.compareAndSwapObject(this, TAIL, cmp, val); |
540 |
> |
return TAIL.compareAndSet(this, cmp, val); |
541 |
|
} |
542 |
|
|
543 |
|
private boolean casHead(Node cmp, Node val) { |
544 |
< |
return U.compareAndSwapObject(this, HEAD, cmp, val); |
544 |
> |
return HEAD.compareAndSet(this, cmp, val); |
545 |
|
} |
546 |
|
|
547 |
|
private boolean casSweepVotes(int cmp, int val) { |
548 |
< |
return U.compareAndSwapInt(this, SWEEPVOTES, cmp, val); |
548 |
> |
return SWEEPVOTES.compareAndSet(this, cmp, val); |
549 |
|
} |
550 |
|
|
551 |
|
/* |
1532 |
|
} |
1533 |
|
} |
1534 |
|
|
1535 |
< |
// Unsafe mechanics |
1536 |
< |
|
1537 |
< |
private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); |
1538 |
< |
private static final long HEAD; |
1540 |
< |
private static final long TAIL; |
1541 |
< |
private static final long SWEEPVOTES; |
1535 |
> |
// VarHandle mechanics |
1536 |
> |
private static final VarHandle HEAD; |
1537 |
> |
private static final VarHandle TAIL; |
1538 |
> |
private static final VarHandle SWEEPVOTES; |
1539 |
|
static { |
1540 |
|
try { |
1541 |
< |
HEAD = U.objectFieldOffset |
1542 |
< |
(LinkedTransferQueue.class.getDeclaredField("head")); |
1543 |
< |
TAIL = U.objectFieldOffset |
1544 |
< |
(LinkedTransferQueue.class.getDeclaredField("tail")); |
1545 |
< |
SWEEPVOTES = U.objectFieldOffset |
1546 |
< |
(LinkedTransferQueue.class.getDeclaredField("sweepVotes")); |
1541 |
> |
MethodHandles.Lookup l = MethodHandles.lookup(); |
1542 |
> |
HEAD = l.findVarHandle(LinkedTransferQueue.class, "head", |
1543 |
> |
Node.class); |
1544 |
> |
TAIL = l.findVarHandle(LinkedTransferQueue.class, "tail", |
1545 |
> |
Node.class); |
1546 |
> |
SWEEPVOTES = l.findVarHandle(LinkedTransferQueue.class, "sweepVotes", |
1547 |
> |
int.class); |
1548 |
|
} catch (ReflectiveOperationException e) { |
1549 |
|
throw new Error(e); |
1550 |
|
} |