Skip to content

Commit 5b1a796

Browse files
committed
Optimize release of resources associated by H2 streams: H2StreamHandler#releaseResources should now be called only once
1 parent 49ae683 commit 5b1a796

File tree

1 file changed

+24
-11
lines changed

1 file changed

+24
-11
lines changed

httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.util.concurrent.ConcurrentHashMap;
4141
import java.util.concurrent.ConcurrentLinkedDeque;
4242
import java.util.concurrent.ConcurrentLinkedQueue;
43+
import java.util.concurrent.atomic.AtomicBoolean;
4344
import java.util.concurrent.atomic.AtomicInteger;
4445

4546
import javax.net.ssl.SSLHandshakeException;
@@ -556,7 +557,7 @@ public final void onTimeout(final Timeout timeout) throws HttpException, IOExcep
556557
for (final Iterator<Map.Entry<Integer, H2Stream>> it = streamMap.entrySet().iterator(); it.hasNext(); ) {
557558
final Map.Entry<Integer, H2Stream> entry = it.next();
558559
final H2Stream stream = entry.getValue();
559-
stream.reset(new H2StreamResetException(H2Error.NO_ERROR, "Timeout due to inactivity (" + timeout + ")"));
560+
stream.fail(new H2StreamResetException(H2Error.NO_ERROR, "Timeout due to inactivity (" + timeout + ")"));
560561
}
561562
streamMap.clear();
562563
}
@@ -676,7 +677,7 @@ public final void onException(final Exception cause) {
676677
for (final Iterator<Map.Entry<Integer, H2Stream>> it = streamMap.entrySet().iterator(); it.hasNext(); ) {
677678
final Map.Entry<Integer, H2Stream> entry = it.next();
678679
final H2Stream stream = entry.getValue();
679-
stream.reset(cause);
680+
stream.fail(cause);
680681
}
681682
streamMap.clear();
682683
if (!(cause instanceof ConnectionClosedException)) {
@@ -873,9 +874,8 @@ private void consumeFrame(final RawFrame frame) throws HttpException, IOExceptio
873874
throw new H2ConnectionException(H2Error.FRAME_SIZE_ERROR, "Invalid RST_STREAM frame payload");
874875
}
875876
final int errorCode = payload.getInt();
876-
stream.reset(new H2StreamResetException(errorCode, "Stream reset (" + errorCode + ")"));
877+
stream.fail(new H2StreamResetException(errorCode, "Stream reset (" + errorCode + ")"));
877878
streamMap.remove(streamId);
878-
stream.releaseResources();
879879
requestSessionOutput();
880880
}
881881
}
@@ -1013,7 +1013,7 @@ private void consumeFrame(final RawFrame frame) throws HttpException, IOExceptio
10131013
for (final Iterator<Map.Entry<Integer, H2Stream>> it = streamMap.entrySet().iterator(); it.hasNext(); ) {
10141014
final Map.Entry<Integer, H2Stream> entry = it.next();
10151015
final H2Stream stream = entry.getValue();
1016-
stream.reset(new H2StreamResetException(errorCode, "Connection terminated by the peer (" + errorCode + ")"));
1016+
stream.fail(new H2StreamResetException(errorCode, "Connection terminated by the peer (" + errorCode + ")"));
10171017
}
10181018
streamMap.clear();
10191019
connState = ConnectionHandshake.SHUTDOWN;
@@ -1599,6 +1599,7 @@ static class H2Stream {
15991599
private final H2StreamChannelImpl channel;
16001600
private final H2StreamHandler handler;
16011601
private final boolean remoteInitiated;
1602+
private final AtomicBoolean released;
16021603

16031604
private H2Stream(
16041605
final H2StreamChannelImpl channel,
@@ -1607,6 +1608,7 @@ private H2Stream(
16071608
this.channel = channel;
16081609
this.handler = handler;
16091610
this.remoteInitiated = remoteInitiated;
1611+
this.released = new AtomicBoolean();
16101612
}
16111613

16121614
int getId() {
@@ -1688,15 +1690,21 @@ void produceInputCapacityUpdate() throws IOException {
16881690
handler.updateInputCapacity();
16891691
}
16901692

1691-
void reset(final Exception cause) {
1693+
void fail(final Exception cause) {
16921694
channel.setRemoteEndStream();
16931695
channel.setLocalEndStream();
1694-
handler.failed(cause);
1696+
if (released.compareAndSet(false, true)) {
1697+
handler.failed(cause);
1698+
handler.releaseResources();
1699+
}
16951700
}
16961701

16971702
void localReset(final Exception cause, final int code) throws IOException {
16981703
channel.localReset(code);
1699-
handler.failed(cause);
1704+
if (released.compareAndSet(false, true)) {
1705+
handler.failed(cause);
1706+
handler.releaseResources();
1707+
}
17001708
}
17011709

17021710
void localReset(final Exception cause, final H2Error error) throws IOException {
@@ -1716,17 +1724,22 @@ HandlerFactory<AsyncPushConsumer> getPushHandlerFactory() {
17161724
}
17171725

17181726
void cancel() {
1719-
reset(new RequestNotExecutedException());
1727+
fail(new RequestNotExecutedException());
17201728
}
17211729

17221730
boolean abort() {
17231731
final boolean cancelled = channel.cancel();
1724-
handler.failed(new RequestNotExecutedException());
1732+
if (released.compareAndSet(false, true)) {
1733+
handler.failed(new RequestNotExecutedException());
1734+
handler.releaseResources();
1735+
}
17251736
return cancelled;
17261737
}
17271738

17281739
void releaseResources() {
1729-
handler.releaseResources();
1740+
if (released.compareAndSet(false, true)) {
1741+
handler.releaseResources();
1742+
}
17301743
}
17311744

17321745
void appendState(final StringBuilder buf) {

0 commit comments

Comments
 (0)