00fc239995 HashedWheelTimer introduced test failure

Motivation:
00fc239995 introduced a change to HashedWheelTimerTest which attempted to wait for an explicit event notification until more timer events can be added. However HashedWheelTimer will execute the timer Runnable before removing it from the queue and decrementing the total count. This make it difficult for users to know when it is safe to add another timer task as the limit is approached.

Modifications:
- HashedWheelTimer should remove the timer Runnable before executing the task.

Result:
Users can more reliably add new timers when the limit is reached and HashedWheelTimerTest will no longer fail spuriously due to this race condition.
This commit is contained in:
Scott Mitchell 2016-11-15 20:07:43 -08:00
parent 4bce554c90
commit a0e375bbc0

View File

@ -706,8 +706,9 @@ public class HashedWheelTimer implements Timer {
// process all timeouts
while (timeout != null) {
boolean remove = false;
HashedWheelTimeout next = timeout.next;
if (timeout.remainingRounds <= 0) {
next = remove(timeout);
if (timeout.deadline <= deadline) {
timeout.expire();
} else {
@ -715,22 +716,16 @@ public class HashedWheelTimer implements Timer {
throw new IllegalStateException(String.format(
"timeout.deadline (%d) > deadline (%d)", timeout.deadline, deadline));
}
remove = true;
} else if (timeout.isCancelled()) {
remove = true;
next = remove(timeout);
} else {
timeout.remainingRounds --;
}
// store reference to next as we may null out timeout.next in the remove block.
HashedWheelTimeout next = timeout.next;
if (remove) {
remove(timeout);
}
timeout = next;
}
}
public void remove(HashedWheelTimeout timeout) {
public HashedWheelTimeout remove(HashedWheelTimeout timeout) {
HashedWheelTimeout next = timeout.next;
// remove timeout that was either processed or cancelled by updating the linked-list
if (timeout.prev != null) {
@ -759,6 +754,7 @@ public class HashedWheelTimer implements Timer {
if (timeout.timer.shouldLimitTimeouts()) {
timeout.timer.pendingTimeouts.decrementAndGet();
}
return next;
}
/**