import java.util.LinkedList; /** * Allows global state snapshots to be passed between threads, * thus giving safe communication between graphics and simulation components */ public class SynchronousStateQueue { LinkedList m_listSwarm; double m_lfTimeLastFrame; double m_lfTimeLastSim; public SynchronousStateQueue() { m_lfTimeLastFrame = 0.0; m_lfTimeLastSim = 0.0; m_listSwarm = new LinkedList(); } /** * gets a copy of the least recent state in the queue, returns * lclCache if the timestamp of lclCache matches that of the * least recent state. * @param lclCache to prevent excessive copying should this be * called multiple times, anything passed as "lclCache" should * only be touched by one thread. * @return copy of least recent swarm state, or lclCache if * lclCache's timestamp matches that of the least recent state. */ public synchronized SwarmState getLeastRecent(SwarmState lclCache) { // front of queue is least recent // use removeFirst, addLast and getFirst if(m_listSwarm.size() < 1) { System.out.println("Local cache"); return new SwarmState(lclCache); } SwarmState stateFirst = m_listSwarm.getFirst(); if(lclCache != null && stateFirst.getTime() == lclCache.getTime()) { System.out.println("Local cache"); return new SwarmState(lclCache); } m_lfTimeLastFrame = stateFirst.getTime(); return new SwarmState(stateFirst); } /** * removes all elements on the queue corresonding to times * less then lfTime, unless doing so empties queue, in which case * it leaves the last element. * @param lfTime remove all elements before this time (except for * last element in the queue) * @return number of elements removed */ public synchronized int removeBefore(double lfTime) { int nCnt = 0; if(m_listSwarm.size() <= 1) { return 0; } SwarmState stateFirst = m_listSwarm.getFirst(); while(stateFirst.getTime() < lfTime && m_listSwarm.size() > 1) { m_listSwarm.removeFirst(); stateFirst = m_listSwarm.getFirst(); ++nCnt; } return nCnt; } /** * push another simulated state onto the queue, * return the difference in (simulation) time between the * last frame requested by the drawing engine and the last frame * pushed on by the simulator * graph must be copied before calling this. */ public synchronized double addState(double [] arrLfPositions, StateBundle [] arrStates, IAgent agent, double lfTime, CommGraph graph) { SwarmState pushMe = new SwarmState(arrLfPositions, arrStates, agent, lfTime, graph); m_listSwarm.addLast(pushMe); m_lfTimeLastSim = lfTime; return m_lfTimeLastSim - m_lfTimeLastFrame; } /** * push another simulated state onto the queue, but only if the queue * is empty * return the difference in (simulation) time between the * last frame requested by the drawing engine and the last frame * pushed on by the simulator * graph must be copied before calling this. */ public synchronized double addStateIfEmpty(double [] arrLfPositions, StateBundle [] arrStates, IAgent agent, double lfTime, CommGraph graph) { if(m_listSwarm.size() < 1) { SwarmState pushMe = new SwarmState(arrLfPositions, arrStates, agent, lfTime, graph); m_listSwarm.addLast(pushMe); m_lfTimeLastSim = lfTime; return m_lfTimeLastSim - m_lfTimeLastFrame; } return 0; } }