diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java b/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java index c8a0a2cb03e..e2b6d8685ca 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java @@ -12,24 +12,24 @@ import org.eclipse.jetty.util.Callback; /* ------------------------------------------------------------ */ -/** +/** * A Utility class to help implement {@link AsyncEndPoint#write(Object, Callback, ByteBuffer...)} * by calling {@link EndPoint#flush(ByteBuffer...)} until all content is written. - * The abstract method {@link #registerFlushInterest()} is called when not all content has been + * The abstract method {@link #registerFlushInterest()} is called when not all content has been * written after a call to flush and should organise for the {@link #completeWrite()} * method to be called when a subsequent call to flush should be able to make more progress. - * + * */ abstract public class WriteFlusher { private final static ByteBuffer[] NO_BUFFERS= new ByteBuffer[0]; private final AtomicBoolean _writing = new AtomicBoolean(false); private final EndPoint _endp; - + private ByteBuffer[] _buffers; private Object _context; private Callback _callback; - + protected WriteFlusher(EndPoint endp) { _endp=endp; @@ -44,6 +44,10 @@ abstract public class WriteFlusher throw new WritePendingException(); try { + _buffers=buffers; + _context=context; + _callback=callback; + _endp.flush(buffers); // Are we complete? @@ -51,41 +55,44 @@ abstract public class WriteFlusher { if (b.hasRemaining()) { - _buffers=buffers; - _context=context; - _callback=callback; if(registerFlushInterest()) completeWrite(); else _writing.set(true); // Needed as memory barrier - return; } } + + _buffers=null; + _context=null; + _callback=null; + + if (!_writing.compareAndSet(true,false)) + throw new ConcurrentModificationException(); + callback.completed(context); } catch (IOException e) { + _buffers=null; + _context=null; + _callback=null; + if (!_writing.compareAndSet(true,false)) throw new ConcurrentModificationException(e); callback.failed(context,e); - return; } - - if (!_writing.compareAndSet(true,false)) - throw new ConcurrentModificationException(); - callback.completed(context); } - + /* ------------------------------------------------------------ */ /** - * Abstract call to be implemented by specific WriteFlushers. Will return true if a + * Abstract call to be implemented by specific WriteFlushers. Will return true if a * flush is immediately possible, otherwise it will schedule a call to {@link #completeWrite()} or * {@link #failed(Throwable)} when appropriate. * @return true if a flush can proceed. */ abstract protected boolean registerFlushInterest(); - + /* ------------------------------------------------------------ */ /* Remove empty buffers from the start of a multi buffer array */ @@ -100,25 +107,23 @@ abstract public class WriteFlusher return buffers; if (b==buffers.length) return NO_BUFFERS; - + ByteBuffer[] compact=new ByteBuffer[buffers.length-b]; - - for (int i=0;i