001package agent.four;
002
003public final class TimeServerLinked implements TimeServer {
004        private static final class Node {
005                final long waketime;
006                final Agent agent;
007                Node next;
008
009                public Node(long waketime, Agent agent, Node next) {
010                        this.waketime = waketime;
011                        this.agent = agent;
012                        this.next = next;
013                }
014        }
015        private long currentTime;
016        private int size;
017        private Node head;
018
019        /*
020         * Invariant: head != null
021         * Invariant: head.agent == null
022         * Invariant: (size == 0) iff (head.next == null)
023         */
024        public TimeServerLinked() {
025                size = 0;
026                head = new Node(0, null, null);
027        }
028
029        public String toString() {
030                StringBuilder sb = new StringBuilder("[");
031                Node node = head.next;
032                String sep = "";
033                while (node != null) {
034                        sb.append(sep).append("(").append(node.waketime).append(",")
035                        .append(node.agent).append(")");
036                        node = node.next;
037                        sep = ";";
038                }
039                sb.append("]");
040                return (sb.toString());
041        }
042
043        public long currentTime() {
044                return currentTime;
045        }
046
047        public void enqueue(long waketime, Agent agent)
048                        throws IllegalArgumentException
049        {
050                if (waketime <= currentTime)
051                        throw new IllegalArgumentException();
052                Node prevElement = head;
053                while ((prevElement.next != null) &&
054                                (prevElement.next.waketime <= waketime)) {
055                        prevElement = prevElement.next;
056                }
057                Node newElement = new Node(waketime, agent, prevElement.next);
058                prevElement.next = newElement;
059                size++;
060        }
061
062        Agent dequeue()
063                        throws IndexOutOfBoundsException
064        {
065                if (size < 1)
066                        throw new IndexOutOfBoundsException();
067                Agent rval = head.next.agent;
068                head.next = head.next.next;
069                size--;
070                return rval;
071        }
072
073        int size() {
074                return size;
075        }
076
077        boolean empty() {
078                return size() == 0;
079        }
080
081        public void run(int duration) {
082                long endtime = currentTime + duration;
083                while ((!empty()) && (head.next.waketime <= endtime)) {
084                        currentTime = head.next.waketime;
085
086                        Node next = head.next;
087                        while (next!=null && (next.waketime == currentTime)) {
088                                next.agent.check();
089                                next=next.next;
090                        }
091                        while ((!empty()) && (head.next.waketime == currentTime)) {
092                                dequeue().run();
093                        }
094                }
095                currentTime = endtime;
096        }
097}