01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package agent;

import java.util.Observable;

public final class TimeServerLinked extends Observable implements TimeServer {
  private static final class Node {
    final double waketime;
    final Agent agent;
    Node next;

    public Node(double waketime, Agent agent, Node next) {
      this.waketime = waketime;
      this.agent = agent;
      this.next = next;
    }
  }
  private double currentTime;
  private int size;
  private Node head;

  /*
   * Invariant: head != null
   * Invariant: head.agent == null
   * Invariant: (size == 0) iff (head.next == null)
   */
  public TimeServerLinked() {
    size = 0;
    head = new Node(0, null, null);
  }

  public String toString() {
    StringBuilder sb = new StringBuilder("[");
    Node node = head.next;
    String sep = "";
    while (node != null) {
      sb.append(sep).append("(").append(node.waketime).append(",")
      .append(node.agent).append(")");
      node = node.next;
      sep = ";";
    }
    sb.append("]");
    return (sb.toString());
  }

  public double currentTime() {
    return currentTime;
  }

  public void enqueue(double waketime, Agent agent)
      throws IllegalArgumentException
  {
    if (waketime < currentTime)
      throw new IllegalArgumentException();
    Node prevElement = head;
    while ((prevElement.next != null) &&
        (prevElement.next.waketime <= waketime)) {
      prevElement = prevElement.next;
    }
    Node newElement = new Node(waketime, agent, prevElement.next);
    prevElement.next = newElement;
    size++;
  }

  Agent dequeue()
  {
    if (size < 1)
      throw new java.util.NoSuchElementException();
    Agent rval = head.next.agent;
    head.next = head.next.next;
    size--;
    return rval;
  }

  int size() {
    return size;
  }

  boolean empty() {
    return size() == 0;
  }

  public void run(double duration) {
    double endtime = currentTime + duration;
    while ((!empty()) && (head.next.waketime <= endtime)) {
      if ((currentTime - head.next.waketime) < 1e-09) {
        super.setChanged();
        super.notifyObservers();
      }
      currentTime = head.next.waketime;
      dequeue().run();
    }
    currentTime = endtime;
  }
}