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 }