package com.limegroup.gnutella.io; import com.limegroup.gnutella.util.BinaryHeap; /** * Keeps track of a bunch of things that want to be timed out. */ public class TimeoutController { private final BinaryHeap items = new BinaryHeap(20, true); /** Adds a timeoutable to be timed out at timeout + now. */ public void addTimeout(Timeoutable t, long now, long timeout) { items.insert(new Timeout(t, now, timeout)); } /** * Processes all the items that can be timed out. */ public void processTimeouts(long now) { while(!items.isEmpty()) { Timeout t = (Timeout)items.getMax(); if(t != null && now >= t.expireTime) t.timeoutable.notifyTimeout(now, t.expireTime, t.timeoutLength); else break; items.extractMax(); // remove it -- we only peeked before. } } /** Gets the length of time till the next timeoutable expires. -1 for never. */ public long getNextExpireTime() { if(items.isEmpty()) return -1; else return ((Timeout)items.getMax()).expireTime; } /** Keep an expireTime & timeoutable together as one happy couple. */ private static class Timeout implements Comparable { private long expireTime; private Timeoutable timeoutable; private long timeoutLength; Timeout(Timeoutable timeoutable, long now, long timeout) { this.expireTime = now + timeout; this.timeoutLength = timeout; this.timeoutable = timeoutable; } /** * Makes items that expire sooner considered 'larger' so the max BinaryHeap is * sorted correctly */ public int compareTo(Object o) { Timeout b = (Timeout)o; return expireTime < b.expireTime ? 1 : expireTime > b.expireTime ? -1 : 0; } } }