diff --git a/components/net/sf/briar/transport/IncomingErrorCorrectionLayerImpl.java b/components/net/sf/briar/transport/IncomingErrorCorrectionLayerImpl.java index babbfaa7b5ffce3083abab1e880e59b9c140ba50..e20ac44d79a0f3a9211a848cfaaca947d2d2ffcc 100644 --- a/components/net/sf/briar/transport/IncomingErrorCorrectionLayerImpl.java +++ b/components/net/sf/briar/transport/IncomingErrorCorrectionLayerImpl.java @@ -1,9 +1,11 @@ package net.sf.briar.transport; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; import net.sf.briar.api.FormatException; import net.sf.briar.api.transport.Segment; @@ -15,6 +17,7 @@ class IncomingErrorCorrectionLayerImpl implements IncomingErrorCorrectionLayer { private final int n, k; private final Map<Long, Integer> discardCounts; private final Map<Long, Segment[]> segmentSets; + private final ArrayList<Segment> freeSegments; IncomingErrorCorrectionLayerImpl(IncomingEncryptionLayer in, ErasureDecoder decoder, int n, int k) { @@ -24,24 +27,37 @@ class IncomingErrorCorrectionLayerImpl implements IncomingErrorCorrectionLayer { this.k = k; discardCounts = new HashMap<Long, Integer>(); segmentSets = new HashMap<Long, Segment[]>(); + freeSegments = new ArrayList<Segment>(); } public boolean readFrame(Frame f, FrameWindow window) throws IOException, InvalidDataException { // Free any segment sets that have been removed from the window - Iterator<Long> it = segmentSets.keySet().iterator(); - while(it.hasNext()) if(!window.contains(it.next())) it.remove(); + Iterator<Entry<Long, Segment[]>> it = segmentSets.entrySet().iterator(); + while(it.hasNext()) { + Entry<Long, Segment[]> e = it.next(); + if(!window.contains(e.getKey())) { + it.remove(); + for(Segment s : e.getValue()) if(s != null) freeSegments.add(s); + } + } // Free any discard counts that are no longer too high for the window Iterator<Long> it1 = discardCounts.keySet().iterator(); while(it1.hasNext()) if(!window.isTooHigh(it1.next())) it1.remove(); - // FIXME: Unnecessary allocation - Segment s = new SegmentImpl(); + // Grab a free segment, or allocate one if necessary + Segment s; + int free = freeSegments.size(); + if(free == 0) s = new SegmentImpl(); + else s = freeSegments.remove(free - 1); // Read segments until a frame can be decoded while(true) { // Read segments until a segment in the window is returned long frameNumber; while(true) { - if(!in.readSegment(s)) return false; + if(!in.readSegment(s)) { + freeSegments.add(s); + return false; + } frameNumber = s.getSegmentNumber() / n; if(window.contains(frameNumber)) break; if(window.isTooHigh(frameNumber)) countDiscard(frameNumber);