private static <I extends StreamSourceChannel, O extends StreamSinkChannel> void done( I source, O sink, ChannelListener<? super I> sourceListener, ChannelListener<? super O> sinkListener) { Channels.setReadListener(source, sourceListener); if (sourceListener == null) { source.suspendReads(); } else { source.wakeupReads(); } Channels.setWriteListener(sink, sinkListener); if (sinkListener == null) { sink.suspendWrites(); } else { sink.wakeupWrites(); } }
public void handleEvent(final Channel channel) { if (done) { if (channel instanceof StreamSinkChannel) { ((StreamSinkChannel) channel).suspendWrites(); } else if (channel instanceof StreamSourceChannel) { ((StreamSourceChannel) channel).suspendReads(); } return; } boolean noWrite = false; if (pooledBuffer == null) { pooledBuffer = pool.allocate(); noWrite = true; } else if (channel instanceof StreamSourceChannel) { noWrite = true; // attempt a read first, as this is a read notification pooledBuffer.getResource().compact(); } final ByteBuffer buffer = pooledBuffer.getResource(); try { long read; for (; ; ) { boolean writeFailed = false; // always attempt to write first if we have the buffer if (!noWrite) { while (buffer.hasRemaining()) { final int res; try { res = sink.write(buffer); } catch (IOException e) { pooledBuffer.free(); pooledBuffer = null; done = true; ChannelListeners.invokeChannelExceptionHandler(sink, writeExceptionHandler, e); return; } if (res == 0) { writeFailed = true; break; } } if (sourceDone && !buffer.hasRemaining()) { done = true; done(source, sink, sourceListener, sinkListener); return; } buffer.compact(); } noWrite = false; if (buffer.hasRemaining() && !sourceDone) { try { read = source.read(buffer); buffer.flip(); } catch (IOException e) { pooledBuffer.free(); pooledBuffer = null; done = true; ChannelListeners.invokeChannelExceptionHandler(source, readExceptionHandler, e); return; } if (read == 0) { break; } else if (read == -1) { sourceDone = true; if (!buffer.hasRemaining()) { done = true; done(source, sink, sourceListener, sinkListener); return; } } } else { buffer.flip(); if (writeFailed) { break; } } } // suspend writes if there is nothing to write if (!buffer.hasRemaining()) { sink.suspendWrites(); } else if (!sink.isWriteResumed()) { sink.resumeWrites(); } // suspend reads if there is nothing to read if (buffer.remaining() == buffer.capacity()) { source.suspendReads(); } else if (!source.isReadResumed()) { source.resumeReads(); } } finally { if (pooledBuffer != null && !buffer.hasRemaining()) { pooledBuffer.free(); pooledBuffer = null; } } }