Added a potential fix for infinite loop in LinkedTransferQueue.clean()
This commit is contained in:
parent
92bbc4acec
commit
b876bd8cec
@ -95,6 +95,8 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E> implements Blocking
|
||||
/** The number of CPUs, for spin control */
|
||||
private static final int NCPUS = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
private static final QNode UNDEFINED = new QNode(null, false);
|
||||
|
||||
/**
|
||||
* The number of times to spin before blocking in timed waits.
|
||||
* The value is empirically derived -- it works well across a
|
||||
@ -345,7 +347,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E> implements Blocking
|
||||
* Gets rid of cancelled node s with original predecessor pred.
|
||||
* @return null (to simplify use by callers)
|
||||
*/
|
||||
Object clean(QNode pred, QNode s) {
|
||||
Object clean(final QNode pred, final QNode s) {
|
||||
Thread w = s.waiter;
|
||||
if (w != null) { // Wake up thread
|
||||
s.waiter = null;
|
||||
@ -354,6 +356,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E> implements Blocking
|
||||
}
|
||||
}
|
||||
|
||||
QNode olddp = UNDEFINED;
|
||||
for (;;) {
|
||||
if (pred.next != s) {
|
||||
return null;
|
||||
@ -382,6 +385,8 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E> implements Blocking
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
boolean stateUnchanged = true;
|
||||
QNode dp = cleanMe.get();
|
||||
if (dp != null) { // Try unlinking previous cancelled node
|
||||
QNode d = dp.next;
|
||||
@ -394,10 +399,17 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E> implements Blocking
|
||||
dn != d && // that is on list
|
||||
dp.casNext(d, dn)) {
|
||||
cleanMe.compareAndSet(dp, null);
|
||||
stateUnchanged = false;
|
||||
}
|
||||
if (dp == pred) {
|
||||
return null; // s is already saved node
|
||||
}
|
||||
|
||||
if (stateUnchanged && olddp == dp) {
|
||||
return null; // infinite loop expected - bail out
|
||||
} else {
|
||||
olddp = dp;
|
||||
}
|
||||
}
|
||||
else if (cleanMe.compareAndSet(null, pred)) {
|
||||
return null; // Postpone cleaning s
|
||||
|
Loading…
Reference in New Issue
Block a user