View Javadoc

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  }