Removed Timeout.extend() operation - a user can just create a new timeout
This commit is contained in:
parent
baea5f7a00
commit
60befc196f
@ -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");
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user