212 |
|
this.item = item; |
213 |
|
} |
214 |
|
|
215 |
– |
static final AtomicReferenceFieldUpdater<SNode, SNode> |
216 |
– |
nextUpdater = AtomicReferenceFieldUpdater.newUpdater |
217 |
– |
(SNode.class, SNode.class, "next"); |
218 |
– |
|
215 |
|
boolean casNext(SNode cmp, SNode val) { |
216 |
< |
return (cmp == next && |
217 |
< |
nextUpdater.compareAndSet(this, cmp, val)); |
216 |
> |
return cmp == next && |
217 |
> |
UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); |
218 |
|
} |
219 |
|
|
224 |
– |
static final AtomicReferenceFieldUpdater<SNode, SNode> |
225 |
– |
matchUpdater = AtomicReferenceFieldUpdater.newUpdater |
226 |
– |
(SNode.class, SNode.class, "match"); |
227 |
– |
|
220 |
|
/** |
221 |
|
* Tries to match node s to this node, if so, waking up thread. |
222 |
|
* Fulfillers call tryMatch to identify their waiters. |
227 |
|
*/ |
228 |
|
boolean tryMatch(SNode s) { |
229 |
|
if (match == null && |
230 |
< |
matchUpdater.compareAndSet(this, null, s)) { |
230 |
> |
UNSAFE.compareAndSwapObject(this, matchOffset, null, s)) { |
231 |
|
Thread w = waiter; |
232 |
|
if (w != null) { // waiters need at most one unpark |
233 |
|
waiter = null; |
242 |
|
* Tries to cancel a wait by matching node to itself. |
243 |
|
*/ |
244 |
|
void tryCancel() { |
245 |
< |
matchUpdater.compareAndSet(this, null, this); |
245 |
> |
UNSAFE.compareAndSwapObject(this, matchOffset, null, this); |
246 |
|
} |
247 |
|
|
248 |
|
boolean isCancelled() { |
249 |
|
return match == this; |
250 |
|
} |
251 |
+ |
|
252 |
+ |
// Unsafe mechanics |
253 |
+ |
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); |
254 |
+ |
private static final long nextOffset = |
255 |
+ |
objectFieldOffset(UNSAFE, "next", SNode.class); |
256 |
+ |
private static final long matchOffset = |
257 |
+ |
objectFieldOffset(UNSAFE, "match", SNode.class); |
258 |
+ |
|
259 |
|
} |
260 |
|
|
261 |
|
/** The head (top) of the stack */ |
262 |
|
volatile SNode head; |
263 |
< |
|
264 |
< |
static final AtomicReferenceFieldUpdater<TransferStack, SNode> |
265 |
< |
headUpdater = AtomicReferenceFieldUpdater.newUpdater |
266 |
< |
(TransferStack.class, SNode.class, "head"); |
267 |
< |
|
263 |
> |
|
264 |
|
boolean casHead(SNode h, SNode nh) { |
265 |
< |
return h == head && headUpdater.compareAndSet(this, h, nh); |
265 |
> |
return h == head && |
266 |
> |
UNSAFE.compareAndSwapObject(this, headOffset, h, nh); |
267 |
|
} |
268 |
|
|
269 |
|
/** |
467 |
|
p = n; |
468 |
|
} |
469 |
|
} |
470 |
+ |
|
471 |
+ |
// Unsafe mechanics |
472 |
+ |
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); |
473 |
+ |
private static final long headOffset = |
474 |
+ |
objectFieldOffset(UNSAFE, "head", TransferStack.class); |
475 |
+ |
|
476 |
|
} |
477 |
|
|
478 |
|
/** Dual Queue */ |
498 |
|
this.isData = isData; |
499 |
|
} |
500 |
|
|
498 |
– |
static final AtomicReferenceFieldUpdater<QNode, QNode> |
499 |
– |
nextUpdater = AtomicReferenceFieldUpdater.newUpdater |
500 |
– |
(QNode.class, QNode.class, "next"); |
501 |
– |
|
501 |
|
boolean casNext(QNode cmp, QNode val) { |
502 |
< |
return (next == cmp && |
503 |
< |
nextUpdater.compareAndSet(this, cmp, val)); |
502 |
> |
return next == cmp && |
503 |
> |
UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); |
504 |
|
} |
505 |
|
|
507 |
– |
static final AtomicReferenceFieldUpdater<QNode, Object> |
508 |
– |
itemUpdater = AtomicReferenceFieldUpdater.newUpdater |
509 |
– |
(QNode.class, Object.class, "item"); |
510 |
– |
|
506 |
|
boolean casItem(Object cmp, Object val) { |
507 |
< |
return (item == cmp && |
508 |
< |
itemUpdater.compareAndSet(this, cmp, val)); |
507 |
> |
return item == cmp && |
508 |
> |
UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val); |
509 |
|
} |
510 |
|
|
511 |
|
/** |
512 |
|
* Tries to cancel by CAS'ing ref to this as item. |
513 |
|
*/ |
514 |
|
void tryCancel(Object cmp) { |
515 |
< |
itemUpdater.compareAndSet(this, cmp, this); |
515 |
> |
UNSAFE.compareAndSwapObject(this, itemOffset, cmp, this); |
516 |
|
} |
517 |
< |
|
517 |
> |
|
518 |
|
boolean isCancelled() { |
519 |
|
return item == this; |
520 |
|
} |
527 |
|
boolean isOffList() { |
528 |
|
return next == this; |
529 |
|
} |
530 |
+ |
|
531 |
+ |
// Unsafe mechanics |
532 |
+ |
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); |
533 |
+ |
private static final long nextOffset = |
534 |
+ |
objectFieldOffset(UNSAFE, "next", QNode.class); |
535 |
+ |
private static final long itemOffset = |
536 |
+ |
objectFieldOffset(UNSAFE, "item", QNode.class); |
537 |
|
} |
538 |
|
|
539 |
|
/** Head of queue */ |
553 |
|
tail = h; |
554 |
|
} |
555 |
|
|
554 |
– |
static final AtomicReferenceFieldUpdater<TransferQueue, QNode> |
555 |
– |
headUpdater = AtomicReferenceFieldUpdater.newUpdater |
556 |
– |
(TransferQueue.class, QNode.class, "head"); |
557 |
– |
|
556 |
|
/** |
557 |
|
* Tries to cas nh as new head; if successful, unlink |
558 |
|
* old head's next node to avoid garbage retention. |
559 |
|
*/ |
560 |
|
void advanceHead(QNode h, QNode nh) { |
561 |
< |
if (h == head && headUpdater.compareAndSet(this, h, nh)) |
561 |
> |
if (h == head && |
562 |
> |
UNSAFE.compareAndSwapObject(this, headOffset, h, nh)) |
563 |
|
h.next = h; // forget old next |
564 |
|
} |
565 |
|
|
567 |
– |
static final AtomicReferenceFieldUpdater<TransferQueue, QNode> |
568 |
– |
tailUpdater = AtomicReferenceFieldUpdater.newUpdater |
569 |
– |
(TransferQueue.class, QNode.class, "tail"); |
570 |
– |
|
566 |
|
/** |
567 |
|
* Tries to cas nt as new tail. |
568 |
|
*/ |
569 |
|
void advanceTail(QNode t, QNode nt) { |
570 |
|
if (tail == t) |
571 |
< |
tailUpdater.compareAndSet(this, t, nt); |
571 |
> |
UNSAFE.compareAndSwapObject(this, tailOffset, t, nt); |
572 |
|
} |
573 |
|
|
579 |
– |
static final AtomicReferenceFieldUpdater<TransferQueue, QNode> |
580 |
– |
cleanMeUpdater = AtomicReferenceFieldUpdater.newUpdater |
581 |
– |
(TransferQueue.class, QNode.class, "cleanMe"); |
582 |
– |
|
574 |
|
/** |
575 |
|
* Tries to CAS cleanMe slot. |
576 |
|
*/ |
577 |
|
boolean casCleanMe(QNode cmp, QNode val) { |
578 |
< |
return (cleanMe == cmp && |
579 |
< |
cleanMeUpdater.compareAndSet(this, cmp, val)); |
578 |
> |
return cleanMe == cmp && |
579 |
> |
UNSAFE.compareAndSwapObject(this, cleanMeOffset, cmp, val); |
580 |
|
} |
581 |
|
|
582 |
|
/** |
761 |
|
return; // Postpone cleaning s |
762 |
|
} |
763 |
|
} |
764 |
+ |
|
765 |
+ |
// unsafe mechanics |
766 |
+ |
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); |
767 |
+ |
private static final long headOffset = |
768 |
+ |
objectFieldOffset(UNSAFE, "head", TransferQueue.class); |
769 |
+ |
private static final long tailOffset = |
770 |
+ |
objectFieldOffset(UNSAFE, "tail", TransferQueue.class); |
771 |
+ |
private static final long cleanMeOffset = |
772 |
+ |
objectFieldOffset(UNSAFE, "cleanMe", TransferQueue.class); |
773 |
+ |
|
774 |
|
} |
775 |
|
|
776 |
|
/** |
1113 |
|
transferer = new TransferStack(); |
1114 |
|
} |
1115 |
|
|
1116 |
+ |
// Unsafe mechanics |
1117 |
+ |
static long objectFieldOffset(sun.misc.Unsafe UNSAFE, |
1118 |
+ |
String field, Class<?> klazz) { |
1119 |
+ |
try { |
1120 |
+ |
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); |
1121 |
+ |
} catch (NoSuchFieldException e) { |
1122 |
+ |
// Convert Exception to corresponding Error |
1123 |
+ |
NoSuchFieldError error = new NoSuchFieldError(field); |
1124 |
+ |
error.initCause(e); |
1125 |
+ |
throw error; |
1126 |
+ |
} |
1127 |
+ |
} |
1128 |
+ |
|
1129 |
|
} |