SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
DoublyLinked.java
1/*
2 * Class: DoublyLinked
3 * Description: implementation of class EventList using a doubly-linked list
4 * Environment: Java
5 * Software: SSJ
6 * Copyright (C) 2001 Pierre L'Ecuyer and Universite de Montreal
7 * Organization: DIRO, Universite de Montreal
8 * @author
9 * @since
10 *
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 */
25package umontreal.ssj.simevents.eventlist;
26
27import java.util.Iterator;
28import java.util.ListIterator;
29import java.util.ConcurrentModificationException;
30import java.util.NoSuchElementException;
31import umontreal.ssj.util.PrintfFormat;
32import umontreal.ssj.simevents.Event;
33
44public class DoublyLinked implements EventList {
45 private int modCount = 0;
46
47 // First and last elements in the list.
48 private Node first = null, last = null;
49
50 public boolean isEmpty() {
51 return first == null;
52 }
53
54 public void clear() {
55 if (first == null)
56 return;
57
58 last.succ = null;
59 last = first = null;
60 ++modCount;
61 }
62
63 public void add(Event ev) {
64 Node newNode;
65 newNode = new Node();
66
67 newNode.ev = ev;
68 ++modCount;
69 if (last == null) { // Easy: the event list was empty.
70 first = last = newNode;
71 first.prec = first.succ = null;
72 return;
73 }
74
75 Node node = findPosition(ev); // Finds where to insert.
76 if (node == null) { // Must be inserted first.
77 newNode.succ = first;
78 newNode.succ.prec = newNode;
79 first = newNode;
80 newNode.prec = null;
81 } else { // Insert after node.
82 newNode.prec = node;
83 newNode.succ = node.succ;
84 node.succ = newNode;
85 if (newNode.succ != null)
86 newNode.succ.prec = newNode;
87 else
88 last = newNode;
89 }
90 }
91
92 public void addFirst(Event ev) {
93 Node newNode;
94 newNode = new Node();
95
96 newNode.ev = ev;
97 newNode.prec = null;
98 if (first == null) {
99 first = last = newNode;
100 first.succ = null;
101 } else {
102 newNode.succ = first;
103 first.prec = newNode;
104 first = newNode;
105 }
106 ++modCount;
107 }
108
109 public void addBefore(Event ev, Event other) {
110 Node node = last;
111 while (node != null && node.ev.compareTo(other) >= 0 && node.ev != other)
112 node = node.prec;
113 if (node.ev != other)
114 throw new IllegalArgumentException("Event not in list.");
115
116 Node newNode;
117 newNode = new Node();
118
119 newNode.ev = ev;
120
121 newNode.prec = node.prec;
122 newNode.succ = node;
123 node.prec = newNode;
124 if (newNode.prec != null)
125 newNode.prec.succ = newNode;
126 else
127 first = newNode;
128 ++modCount;
129 }
130
131 public void addAfter(Event ev, Event other) {
132 Node node = last;
133 while (node != null && node.ev.compareTo(other) >= 0 && node.ev != other)
134 node = node.prec;
135 if (node.ev != other)
136 throw new IllegalArgumentException("Event not in list.");
137
138 Node newNode;
139 newNode = new Node();
140
141 newNode.ev = ev;
142
143 newNode.prec = node;
144 newNode.succ = node.succ;
145 node.succ = newNode;
146 if (newNode.succ != null)
147 newNode.succ.prec = newNode;
148 else
149 last = newNode;
150 ++modCount;
151 }
152
153 public Event getFirst() {
154 return first == null ? null : first.ev;
155 }
156
157 public Event getFirstOfClass(String cl) {
158 Node node = first;
159 while (node != null) {
160 if (node.ev.getClass().getName().equals(cl))
161 return node.ev;
162 node = node.succ;
163 }
164 return null;
165 }
166
167 @SuppressWarnings("unchecked")
168 public <E extends Event> E getFirstOfClass(Class<E> cl) {
169 Node node = first;
170 while (node != null) {
171 if (node.ev.getClass() == cl)
172 return (E) node.ev;
173 node = node.succ;
174 }
175 return null;
176 }
177
178 public boolean remove(Event ev) {
179 // Find the node corresponding to this event ev.
180 Node node = last;
181 while (node != null && node.ev.compareTo(ev) >= 0 && node.ev != ev)
182 node = node.prec;
183 if (node == null || node.ev != ev)
184 return false;
185
186 if (node == last && node == first)
187 last = first = null; // The list is now empty.
188 else {
189 if (node == last) {
190 last = node.prec;
191 last.succ = null;
192 } else
193 node.succ.prec = node.prec;
194 if (node == first) {
195 first = node.succ;
196 first.prec = null;
197 } else {
198 node.prec.succ = node.succ;
199 node.prec = null;
200 }
201 }
202 node.ev = null;
203 node.succ = null;
204
205 ++modCount;
206 return true;
207 }
208
210 if (first == null)
211 return null;
212
213 Event ev = first.ev;
214 Node temp = first;
215 first = first.succ;
216 if (first == null)
217 last = null;
218 else
219 first.prec = null;
220
221 temp.ev = null;
222 temp.succ = null;
223
224 ++modCount;
225 return ev;
226 }
227
228 public Iterator<Event> iterator() {
229 return listIterator();
230 }
231
232 public ListIterator<Event> listIterator() {
233 return new DLItr();
234 }
235
236 public String toString() {
237 StringBuilder sb = new StringBuilder("Contents of the event list DoublyLinked:");
238 Node node = first;
239 while (node != null) {
240 sb.append(PrintfFormat.NEWLINE + PrintfFormat.g(12, 7, node.ev.time()) + ", "
241 + PrintfFormat.g(8, 4, node.ev.priority()) + " : " + node.ev.toString());
242 node = node.succ;
243 }
244 return sb.toString();
245 }
246
247 // A element of the event list. This node contains the event ev.
248 // His predecessor and successor are prec and succ.
249 private static class Node {
250 Event ev;
251 Node prec, succ;
252 }
253
254 private class DLItr implements ListIterator<Event> {
255 private Node prev;
256 private Node next;
257 private Node lastRet;
258 private int expectedModCount;
259 private int nextIndex;
260
261 DLItr() {
262 prev = null;
263 next = first;
264 expectedModCount = modCount;
265 lastRet = null;
266 nextIndex = 0;
267 }
268
269 public void add(Event ev) {
270 if (modCount != expectedModCount)
271 throw new ConcurrentModificationException();
272
273 // Check the event time and priority
274 if (next != null && ev.compareTo(next.ev) > 0) {
275 ev.setTime(next.ev.time());
276 ev.setPriority(next.ev.priority());
277 }
278 if (prev != null && ev.compareTo(prev.ev) < 0) {
279 ev.setTime(prev.ev.time());
280 ev.setPriority(prev.ev.priority());
281 }
282
283 Node newNode;
284 newNode = new Node();
285
286 newNode.ev = ev;
287 ++nextIndex;
288 ++modCount;
289 ++expectedModCount;
290 lastRet = null;
291 if (last == null) { // Easy: the event list was empty.
292 first = last = newNode;
293 first.prec = first.succ = null;
294 prev = newNode;
295 next = null;
296 nextIndex = 1;
297 } else if (prev == null) { // Must be inserted first.
298 // next is non-null or the list would be empty.
299 newNode.succ = first;
300 newNode.succ.prec = newNode;
301 first = newNode;
302 newNode.prec = null;
303 prev = newNode;
304 } else { // Insert after node.
305 // prev is non-null but next can be null.
306 newNode.prec = prev;
307 newNode.succ = next;
308 prev.succ = newNode;
309 if (newNode.succ != null)
310 newNode.succ.prec = newNode;
311 else
312 last = newNode;
313 prev = newNode;
314 }
315 }
316
317 public boolean hasNext() {
318 if (modCount != expectedModCount)
319 throw new ConcurrentModificationException();
320 return next != null;
321 }
322
323 public boolean hasPrevious() {
324 if (modCount != expectedModCount)
325 throw new ConcurrentModificationException();
326 return prev != null;
327 }
328
329 public Event next() {
330 if (!hasNext())
331 throw new NoSuchElementException();
332
333 ++nextIndex;
334 Event ev = next.ev;
335 lastRet = next;
336 prev = next;
337 next = next.succ;
338 return ev;
339 }
340
341 public int nextIndex() {
342 if (!hasNext())
343 throw new NoSuchElementException();
344
345 return nextIndex;
346 }
347
348 public Event previous() {
349 if (!hasPrevious())
350 throw new NoSuchElementException();
351
352 --nextIndex;
353 Event ev = prev.ev;
354 lastRet = prev;
355 next = prev;
356 prev = prev.prec;
357 return ev;
358 }
359
360 public int previousIndex() {
361 if (!hasPrevious())
362 throw new NoSuchElementException();
363
364 return nextIndex - 1;
365 }
366
367 public void remove() {
368 if (modCount != expectedModCount)
369 throw new ConcurrentModificationException();
370 if (lastRet == null)
371 throw new IllegalStateException();
372
373 if (lastRet == next) // Last call to previous
374 next = next.succ;
375 else { // Last call to next
376 prev = prev.prec;
377 --nextIndex;
378 }
379 if (lastRet == last && lastRet == first) {
380 last = first = null; // The list is now empty.
381 next = prev = null;
382 } else {
383 if (lastRet == last) {
384 last = lastRet.prec;
385 last.succ = null;
386 } else
387 lastRet.succ.prec = lastRet.prec;
388 if (lastRet == first) {
389 first = lastRet.succ;
390 first.prec = null;
391 } else {
392 lastRet.prec.succ = lastRet.succ;
393 lastRet.prec = null;
394 }
395 }
396 lastRet.ev = null;
397 lastRet.succ = null;
398
399 lastRet = null;
400 ++modCount;
401 ++expectedModCount;
402 }
403
404 public void set(Event ev) {
405 if (modCount != expectedModCount)
406 throw new ConcurrentModificationException();
407 if (lastRet == null)
408 throw new IllegalStateException();
409
410 // Check the event time and priority
411 if (lastRet.prec != null && ev.compareTo(lastRet.prec.ev) < 0) {
412 ev.setTime(lastRet.prec.ev.time());
413 ev.setPriority(lastRet.prec.ev.priority());
414 }
415 if (lastRet.succ != null && ev.compareTo(lastRet.succ.ev) > 0) {
416 ev.setTime(lastRet.succ.ev.time());
417 ev.setPriority(lastRet.succ.ev.priority());
418 }
419
420 lastRet.ev = ev;
421 }
422 }
423
424 private Node findPosition(Event ev) {
425 // This implementation appears quite inefficient !!!!
426 // Must try to improve.
427 Node node = last;
428
429 // Finds the occurrence time of the new event (evTime).
430 while (node != null && ev.compareTo(node.ev) < 0) {
431 node = node.prec;
432 }
433 return node;
434 }
435}
This abstract class provides event scheduling tools.
Definition Event.java:53
int compareTo(Event e)
Compares this object with the specified object e for order.
Definition Event.java:325
An implementation of EventList using a doubly linked linear list.
void addAfter(Event ev, Event other)
Same as add, but adds the new event ev immediately after the event other in the list.
void addFirst(Event ev)
Adds a new event at the beginning of the event list.
boolean isEmpty()
Returns true if and only if the event list is empty (no event is scheduled).
void addBefore(Event ev, Event other)
Same as add, but adds the new event ev immediately before the event other in the list.
ListIterator< Event > listIterator()
Returns a list iterator over the elements of the class Event in this list.
Event getFirstOfClass(String cl)
Returns the first event of the class cl (a subclass of Event) in the event list.
void clear()
Empties the event list, i.e., cancels all events.
Event removeFirst()
Removes the first event from the event list (to cancel or execute this event).
void add(Event ev)
Adds a new event in the event list, according to the time of ev.
Event getFirst()
Returns the first event in the event list.
This class acts like a StringBuffer which defines new types of append methods.
static final String NEWLINE
End-of-line symbol or line separator.
static String g(double x)
Same as g(0, 6, x).
An interface for implementations of event lists.