@Override public final void run(Timeout timeout) throws Exception { if (timeout.isCancelled()) { // reschedule has already been done, don't incur the overhead of redoing it return; } long startPoint = Math.max(getLastIoTimeMillis(), getLastIdleTimeMillis()); // Doing the calculation here avoids having to call currentTimeMillis twice (here and in // reschedule). // Given that the precision of timeout is limited, and that lastIdleTime is only updated if // idle is fired, we must // always call currentTimeMillis(). For example, imagine session idle last fired at t0. // Timeout will occur at or // after t0 + configured idleTime. Even if an I/O event occurred after t0, we may still need // to fire sessionIdle. long timeUntilSessionIdle = startPoint + idleTimeMillis - currentTimeMillis(); if (timeUntilSessionIdle <= 0 && idleTimeMillis != 0) { fireSessionIdle(filterChain); reschedule(idleTimeMillis); } else { // An intervening I/O means we should not fire session idle, but we must reschedule to // ensure accuracy // of when we do fire sessionIdle. reschedule(timeUntilSessionIdle); } }
@Override public void run(Timeout timeout) throws Exception { if (timeout.isCancelled()) { return; } if (!ctx.getChannel().isOpen()) { return; } State state = (State) ctx.getAttachment(); long currentTime = System.currentTimeMillis(); long nextDelay = timeoutMillis - (currentTime - state.lastReadTime); if (nextDelay <= 0) { // Read timed out - set a new timeout and notify the callback. state.timeout = timer.newTimeout(this, timeoutMillis, TimeUnit.MILLISECONDS); try { // FIXME This should be called from an I/O thread. // To be fixed in Netty 4. readTimedOut(ctx); } catch (Throwable t) { fireExceptionCaught(ctx, t); } } else { // Read occurred before the timeout - set a new timeout with shorter delay. state.timeout = timer.newTimeout(this, nextDelay, TimeUnit.MILLISECONDS); } }