2727import java .io .IOException ;
2828import java .nio .ByteBuffer ;
2929import java .util .concurrent .atomic .AtomicBoolean ;
30+ import java .util .concurrent .atomic .AtomicLong ;
3031
3132/**
3233 * A {@link ChunkResponder} that writes chunks to a {@link Channel}.
@@ -35,10 +36,14 @@ final class ChannelChunkResponder implements ChunkResponder {
3536
3637 private final Channel channel ;
3738 private final AtomicBoolean closed ;
39+ private final AtomicLong bufferedSize ;
40+ private final int chunkMemoryLimit ;
3841
39- ChannelChunkResponder (Channel channel ) {
42+ ChannelChunkResponder (Channel channel , int chunkMemoryLimit ) {
4043 this .channel = channel ;
41- this .closed = new AtomicBoolean (false );
44+ this .closed = new AtomicBoolean ();
45+ this .bufferedSize = new AtomicLong ();
46+ this .chunkMemoryLimit = chunkMemoryLimit ;
4247 }
4348
4449 @ Override
@@ -54,14 +59,35 @@ public void sendChunk(ByteBuf chunk) throws IOException {
5459 if (!channel .isActive ()) {
5560 throw new IOException ("Connection already closed." );
5661 }
62+ int chunkSize = chunk .readableBytes ();
5763 channel .write (new DefaultHttpContent (chunk ));
64+ tryFlush (chunkSize );
5865 }
5966
6067 @ Override
61- public void close () throws IOException {
68+ public void flush () {
69+ // Use the limit as the size to force a flush
70+ tryFlush (chunkMemoryLimit );
71+ }
72+
73+ @ Override
74+ public void close () {
6275 if (!closed .compareAndSet (false , true )) {
6376 return ;
6477 }
6578 channel .writeAndFlush (LastHttpContent .EMPTY_LAST_CONTENT );
6679 }
80+
81+ private void tryFlush (int size ) {
82+ long newSize = bufferedSize .addAndGet (size );
83+ if (newSize >= chunkMemoryLimit ) {
84+ channel .flush ();
85+ // Subtract what were flushed.
86+ // This is correct for single thread.
87+ // For concurrent calls, this provides a lower bound,
88+ // meaning more data might get flushed then being subtracted.
89+ // This make sure we won't go over the memory limit, but might flush more often than needed.
90+ bufferedSize .addAndGet (-1 * newSize );
91+ }
92+ }
6793}
0 commit comments