1 package nl.tudelft.goal.ut2004.actions;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Iterator;
6 import java.util.concurrent.BlockingQueue;
7 import java.util.concurrent.LinkedBlockingQueue;
8
9 /**
10 * Smart queue for actions.
11 *
12 * There is a limited bandwidth to transfer actions between GOAL and the
13 * UT2004Bot. GOAL will send actions at a high rate and could saturate the
14 * queue. To prevent this we check which actions are in the queue before adding
15 * a new action.
16 *
17 * There are three possible scenarios:
18 * <ul>
19 * <li>If the effects of a new action would cancel out the effects of an action
20 * in the queue, the queued action is discarded.</li>
21 * <li>If the effects of a new action have no effect on an action in the queue,
22 * the action is put in.</li>
23 * <li>If an action in the queue means the new action has no effect, the new
24 * action id discarded.</li>
25 * </ul>
26 *
27 *
28 * @author mpkorstanje
29 *
30 */
31 public final class ActionQueue {
32
33 /**
34 * Queued up actions. Once the queue if full GOAL has to wait.
35 *
36 */
37 private final BlockingQueue<Action> actions;
38
39 public ActionQueue(int capacity) {
40 actions = new LinkedBlockingQueue<Action>(capacity);
41 }
42
43 /**
44 * Puts an action on the queue. If the queue is full this method will block.
45 *
46 * The action is added intelligently to the queue. Should the results of
47 * this action happened to override or cancel out an action already in the
48 * queue the action in the queue will be removed.
49 *
50 * @param action
51 * @throws InterruptedException
52 */
53 public void put(Action action) throws InterruptedException {
54
55 synchronized (actions) {
56
57 // Check if adding action to queue will have effect
58 for (Action queueAction : actions) {
59 if (!action.hasEffect(queueAction)) {
60 return;
61 }
62 }
63
64 // If adding has effect, check which actions will have no effect.
65 Iterator<Action> itterator = actions.iterator();
66 while (itterator.hasNext()) {
67 Action queueAction = itterator.next();
68
69 if (action.replaces(queueAction)) {
70 itterator.remove();
71 }
72 }
73
74 }
75
76 // Out side of sync block
77 // Don't lock actions while waiting for queue to free up.
78 actions.put(action);
79
80 }
81
82 /**
83 * Drains all actions from the queue.
84 *
85 * @return a collection of actions to be executed.
86 */
87 public Collection<Action> drain() {
88 Collection<Action> drain = new ArrayList<Action>(actions.size());
89 synchronized (actions) {
90 actions.drainTo(drain);
91 }
92
93 return drain;
94 }
95
96 }