NETTY-431 HashedWheelTimer's TimerTask may execute after call to Timeout.cancel()

* Replaced a volatile boolean flag and system date access with an atomic integer flag.
This commit is contained in:
Trustin Lee 2011-08-12 14:03:48 +09:00
parent 1345a00a1a
commit 58cc6aec86

View File

@ -472,11 +472,15 @@ public class HashedWheelTimer implements Timer {
private final class HashedWheelTimeout implements Timeout { private final class HashedWheelTimeout implements Timeout {
private static final int ST_INIT = 0;
private static final int ST_CANCELLED = 1;
private static final int ST_EXPIRED = 2;
private final TimerTask task; private final TimerTask task;
final long deadline; final long deadline;
volatile int stopIndex; volatile int stopIndex;
volatile long remainingRounds; volatile long remainingRounds;
private volatile boolean cancelled; private final AtomicInteger state = new AtomicInteger(ST_INIT);
HashedWheelTimeout(TimerTask task, long deadline) { HashedWheelTimeout(TimerTask task, long deadline) {
this.task = task; this.task = task;
@ -492,26 +496,24 @@ public class HashedWheelTimer implements Timer {
} }
public void cancel() { public void cancel() {
if (isExpired()) { if (!state.compareAndSet(ST_INIT, ST_CANCELLED)) {
// TODO return false
return; return;
} }
cancelled = true;
// Might be called more than once, but doesn't matter.
wheel[stopIndex].remove(this); wheel[stopIndex].remove(this);
} }
public boolean isCancelled() { public boolean isCancelled() {
return cancelled; return state.get() == ST_CANCELLED;
} }
public boolean isExpired() { public boolean isExpired() {
return cancelled || System.currentTimeMillis() > deadline; return state.get() != ST_INIT;
} }
public void expire() { public void expire() {
if (cancelled) { if (!state.compareAndSet(ST_INIT, ST_EXPIRED)) {
return; return;
} }