Removed Timeout.extend() operation - a user can just create a new timeout

This commit is contained in:
Trustin Lee 2009-02-02 03:42:05 +00:00
parent baea5f7a00
commit 60befc196f
3 changed files with 32 additions and 133 deletions

View File

@ -183,7 +183,9 @@ public class HashedWheelTimer implements Timer {
return Collections.unmodifiableSet(unprocessedTimeouts); return Collections.unmodifiableSet(unprocessedTimeouts);
} }
public Timeout newTimeout(TimerTask task, long initialDelay, TimeUnit unit) { public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) {
final long currentTime = System.nanoTime();
if (task == null) { if (task == null) {
throw new NullPointerException("task"); throw new NullPointerException("task");
} }
@ -191,22 +193,34 @@ public class HashedWheelTimer implements Timer {
throw new NullPointerException("unit"); throw new NullPointerException("unit");
} }
initialDelay = unit.toNanos(initialDelay); delay = unit.toNanos(delay);
checkDelay(initialDelay); checkDelay(delay);
if (!workerThread.isAlive()) { if (!workerThread.isAlive()) {
start(); start();
} }
// Add the timeout to the wheel. // Prepare the required parameters to create the timeout object.
HashedWheelTimeout timeout; HashedWheelTimeout timeout;
long currentTime = System.nanoTime(); final long lastRoundDelay = delay % roundDuration;
final long lastTickDelay = delay % tickDuration;
final long relativeIndex =
lastRoundDelay / tickDuration + (lastTickDelay != 0? 1 : 0);
final long deadline = currentTime + delay;
final long remainingRounds =
delay / roundDuration - (delay % roundDuration == 0? 1 : 0);
// Add the timeout to the wheel.
lock.readLock().lock(); lock.readLock().lock();
try { try {
timeout = new HashedWheelTimeout( timeout =
task, wheelCursor, currentTime, initialDelay); new HashedWheelTimeout(
task, deadline,
(int) (wheelCursor + relativeIndex & mask),
remainingRounds);
wheel[schedule(timeout)].add(timeout); wheel[timeout.stopIndex].add(timeout);
} finally { } finally {
lock.readLock().unlock(); lock.readLock().unlock();
} }
@ -214,31 +228,6 @@ public class HashedWheelTimer implements Timer {
return timeout; return timeout;
} }
private int schedule(HashedWheelTimeout timeout) {
return schedule(timeout, timeout.initialDelay);
}
int schedule(HashedWheelTimeout timeout, final long additionalDelay) {
synchronized (timeout) {
final long oldCumulativeDelay = timeout.cumulativeDelay;
final long newCumulativeDelay = oldCumulativeDelay + additionalDelay;
final long lastRoundDelay = newCumulativeDelay % roundDuration;
final long lastTickDelay = newCumulativeDelay % tickDuration;
final long relativeIndex =
lastRoundDelay / tickDuration + (lastTickDelay != 0? 1 : 0);
timeout.deadline = timeout.startTime + newCumulativeDelay;
timeout.cumulativeDelay = newCumulativeDelay;
timeout.remainingRounds =
additionalDelay / roundDuration -
(additionalDelay % roundDuration == 0? 1:0) - timeout.slippedRounds;
timeout.slippedRounds = 0;
return timeout.stopIndex = (int) (timeout.startIndex + relativeIndex & mask);
}
}
boolean isWheelEmpty() { boolean isWheelEmpty() {
for (Set<HashedWheelTimeout> bucket: wheel) { for (Set<HashedWheelTimeout> bucket: wheel) {
if (!bucket.isEmpty()) { if (!bucket.isEmpty()) {
@ -314,7 +303,6 @@ public class HashedWheelTimer implements Timer {
} else { } else {
// A rare case where a timeout is put for the next // A rare case where a timeout is put for the next
// round: just wait for the next round. // round: just wait for the next round.
timeout.slippedRounds ++;
} }
} else { } else {
timeout.remainingRounds --; timeout.remainingRounds --;
@ -366,27 +354,17 @@ public class HashedWheelTimer implements Timer {
private final class HashedWheelTimeout implements Timeout { private final class HashedWheelTimeout implements Timeout {
private final TimerTask task; private final TimerTask task;
final int stopIndex;
final int startIndex; final long deadline;
int stopIndex; volatile long remainingRounds;
final long startTime;
volatile long deadline;
final long initialDelay;
long cumulativeDelay;
long remainingRounds;
long slippedRounds;
private volatile int extensionCount;
private volatile boolean cancelled; private volatile boolean cancelled;
HashedWheelTimeout(TimerTask task, int startIndex, long startTime, long initialDelay) { HashedWheelTimeout(
TimerTask task, long deadline, int stopIndex, long remainingRounds) {
this.task = task; this.task = task;
this.startIndex = startIndex; this.deadline = deadline;
this.startTime = startTime; this.stopIndex = stopIndex;
this.initialDelay = initialDelay; this.remainingRounds = remainingRounds;
} }
public TimerTask getTask() { public TimerTask getTask() {
@ -401,53 +379,7 @@ public class HashedWheelTimer implements Timer {
cancelled = true; cancelled = true;
// Might be called more than once, but doesn't matter. // Might be called more than once, but doesn't matter.
synchronized (this) { wheel[stopIndex].remove(this);
wheel[stopIndex].remove(this);
}
}
public void extend() {
extend(initialDelay);
}
public void extend(long additionalDelay, TimeUnit unit) {
extend(unit.toNanos(additionalDelay));
}
private void extend(long additionalDelay) {
checkDelay(additionalDelay);
if (cancelled) {
throw new IllegalStateException("cancelled");
}
lock.readLock().lock();
try {
// Reinsert the timeout to the appropriate bucket.
int oldStopIndex;
int newStopIndex;
synchronized (this) {
oldStopIndex = stopIndex;
stopIndex = newStopIndex = schedule(this, additionalDelay);
}
// Remove the timeout from the old bucket if necessary.
// If this method is called from the worker thread, it means
// this timeout has been removed from the bucket already.
if (oldStopIndex != newStopIndex &&
Thread.currentThread() != workerThread) {
wheel[oldStopIndex].remove(this);
}
// And add to the new bucket. If added already, that's fine.
wheel[newStopIndex].add(this);
} finally {
extensionCount ++;
lock.readLock().unlock();
}
}
public int getExtensionCount() {
return extensionCount;
} }
public boolean isCancelled() { public boolean isCancelled() {
@ -475,25 +407,12 @@ public class HashedWheelTimer implements Timer {
@Override @Override
public String toString() { public String toString() {
long currentTime = System.nanoTime(); long currentTime = System.nanoTime();
long age = currentTime - startTime;
long remaining = deadline - currentTime; long remaining = deadline - currentTime;
StringBuilder buf = new StringBuilder(192); StringBuilder buf = new StringBuilder(192);
buf.append(getClass().getSimpleName()); buf.append(getClass().getSimpleName());
buf.append('('); buf.append('(');
buf.append("initialDelay: ");
buf.append(initialDelay / 1000000);
buf.append(" ms, ");
buf.append("cumulativeDelay: ");
buf.append(cumulativeDelay / 1000000);
buf.append(" ms, ");
buf.append("started: ");
buf.append(age / 1000000);
buf.append(" ms ago, ");
buf.append("deadline: "); buf.append("deadline: ");
if (remaining > 0) { if (remaining > 0) {
buf.append(remaining / 1000000); buf.append(remaining / 1000000);
@ -505,20 +424,6 @@ public class HashedWheelTimer implements Timer {
buf.append("now, "); buf.append("now, ");
} }
buf.append("extended: ");
switch (getExtensionCount()) {
case 0:
buf.append("never");
break;
case 1:
buf.append("once");
break;
default:
buf.append(getExtensionCount());
buf.append(" times");
break;
}
if (isCancelled()) { if (isCancelled()) {
buf.append (", cancelled"); buf.append (", cancelled");
} }

View File

@ -22,8 +22,6 @@
*/ */
package org.jboss.netty.handler.timeout; package org.jboss.netty.handler.timeout;
import java.util.concurrent.TimeUnit;
/** /**
* @author The Netty Project (netty-dev@lists.jboss.org) * @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com) * @author Trustin Lee (tlee@redhat.com)
@ -34,9 +32,5 @@ public interface Timeout {
boolean isExpired(); boolean isExpired();
boolean isCancelled(); boolean isCancelled();
int getExtensionCount();
void extend();
void extend(long extensionTime, TimeUnit unit);
void cancel(); void cancel();
} }

View File

@ -31,6 +31,6 @@ import java.util.concurrent.TimeUnit;
* @version $Rev$, $Date$ * @version $Rev$, $Date$
*/ */
public interface Timer { public interface Timer {
Timeout newTimeout(TimerTask task, long timeout, TimeUnit unit); Timeout newTimeout(TimerTask task, long delay, TimeUnit unit);
Set<Timeout> stop(); Set<Timeout> stop();
} }