package scd_micro; import java.io.DataOutputStream; import java.io.IOException; /** * Cyclic buffer of frames. Used for frames generated by simulator, but not yet processed by detector. * The memory is allocated at construction time and always re-used (frame data is copied in the same locations). * The frames, as well as the buffer, live in immortal memory. The constructor runs in immortal memory. * Note that the buffer is (intentionally) not synchronized. In a weird combination of priorities that is not * intended to be used, buffer frames could be overwritten. */ public class FrameBuffer { // empty buffer ... first == last // full buffer .... last + 1 == first // - so there is still one empty slot, but we don't want to use it, // because we would not then recognize empty from full buffer // // last .. where the next frame will be stored // first .. where the next frame will be read public int first, last; public RawFrame[] frames; public FrameBuffer() { frames = new RawFrame[Constants.BUFFER_FRAMES]; for (int i = 0; i < Constants.BUFFER_FRAMES; i++) { frames[i] = new RawFrame(); } } public void putFrameInternal(final float[] positions_, final int[] lengths_, final byte[] callsigns_) { if ( (last + 1) % Constants.BUFFER_FRAMES == first) { ImmortalEntry.droppedFrames ++; return; } frames[last].copy(lengths_, callsigns_, positions_); last = (last + 1) % Constants.BUFFER_FRAMES; } static int frameno = 0; public void putFrame(final float[] positions_, final int[] lengths_, final byte[] callsigns_) { if (Constants.SYNCHRONOUS_DETECTOR || Constants.DUMP_SENT_FRAMES) { String prefix = "S-FRAME " + frameno + " "; int offset = 0; for (int i=0;i<lengths_.length;i++) { int cslen = lengths_[i]; System.out.println(prefix+new String( callsigns_, offset, cslen )+" "+ positions_[3*i]+" "+ positions_[3*i+1]+" "+ positions_[3*i+2]+" "); offset += cslen; } frameno++; } // if (Constants.FRAMES_BINARY_DUMP) { // // the binary format: // // nframes <INT> // // // // nplanes <INT> 1 // // positions <FLOAT> nplanes*3 // // lengths <INT> nplanes // // callsigns_length <INT> 1 // // callsigns <BYTE> callsigns_length // // DataOutputStream ds = ImmortalEntry.binaryDumpStream; // // try { // ds.writeInt(lengths_.length); // // for(int i=0; i<lengths_.length; i++) { // ds.writeFloat(positions_[3*i]); // ds.writeFloat(positions_[3*i+1]); // ds.writeFloat(positions_[3*i+2]); // } // // for(int i=0;i<lengths_.length; i++) { // ds.writeInt(lengths_[i]); // } // // ds.writeInt(callsigns_.length); // ds.write(callsigns_); // // } catch (IOException e) { // throw new RuntimeException("Error dumping frames to binary file "+e); // } // // } // if (Constants.SYNCHRONOUS_DETECTOR) { // FrameSynchronizer.produceFrame(); // } putFrameInternal(positions_, lengths_, callsigns_); // if (Constants.SYNCHRONOUS_DETECTOR) { // FrameSynchronizer.waitForConsumer(); // } } public RawFrame getFrame() { if (last == first) { return null; } else { final int f = first; first = (first + 1) % Constants.BUFFER_FRAMES; return frames[f]; // NOTE: if the simulator could run between this and the previous line, // it could corrupt the present frame } } }