This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push: new 0338f2b113 Refactor to reduce pinning in HTTP/2 code when using virtual threads 0338f2b113 is described below commit 0338f2b113295482bacd9ef57264987cb4502f0e Author: Mark Thomas <ma...@apache.org> AuthorDate: Wed Jul 26 14:38:37 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- java/org/apache/coyote/http2/Stream.java | 90 +++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java index d3fc2a7b4c..ff1f24ff12 100644 --- a/java/org/apache/coyote/http2/Stream.java +++ b/java/org/apache/coyote/http2/Stream.java @@ -1112,6 +1112,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { class StandardStreamInputBuffer extends StreamInputBuffer { + private final Lock readStateLock = new ReentrantLock(); /* * Two buffers are required to avoid various multi-threading issues. These issues arise from the fact that the * Stream (or the Request/Response) used by the application is processed in one thread but the connection is @@ -1222,7 +1223,8 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { final boolean isReadyForRead() { ensureBuffersExist(); - synchronized (this) { + readStateLock.lock(); + try { if (available() > 0) { return true; } @@ -1232,21 +1234,33 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { } return false; + } finally { + readStateLock.unlock(); } } @Override - final synchronized boolean isRequestBodyFullyRead() { - return (inBuffer == null || inBuffer.position() == 0) && isInputFinished(); + final boolean isRequestBodyFullyRead() { + readStateLock.lock(); + try { + return (inBuffer == null || inBuffer.position() == 0) && isInputFinished(); + } finally { + readStateLock.unlock(); + } } @Override - public final synchronized int available() { - if (inBuffer == null) { - return 0; + public final int available() { + readStateLock.lock(); + try { + if (inBuffer == null) { + return 0; + } + return inBuffer.position(); + } finally { + readStateLock.unlock(); } - return inBuffer.position(); } @@ -1254,26 +1268,31 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { * Called after placing some data in the inBuffer. */ @Override - final synchronized void onDataAvailable() throws IOException { - if (closed) { - swallowUnread(); - } else if (readInterest) { - if (log.isDebugEnabled()) { - log.debug(sm.getString("stream.inputBuffer.dispatch")); - } - readInterest = false; - coyoteRequest.action(ActionCode.DISPATCH_READ, null); - // Always need to dispatch since this thread is processing - // the incoming connection and streams are processed on their - // own. - coyoteRequest.action(ActionCode.DISPATCH_EXECUTE, null); - } else { - if (log.isDebugEnabled()) { - log.debug(sm.getString("stream.inputBuffer.signal")); - } - synchronized (inBuffer) { - inBuffer.notifyAll(); + final void onDataAvailable() throws IOException { + readStateLock.lock(); + try { + if (closed) { + swallowUnread(); + } else if (readInterest) { + if (log.isDebugEnabled()) { + log.debug(sm.getString("stream.inputBuffer.dispatch")); + } + readInterest = false; + coyoteRequest.action(ActionCode.DISPATCH_READ, null); + // Always need to dispatch since this thread is processing + // the incoming connection and streams are processed on their + // own. + coyoteRequest.action(ActionCode.DISPATCH_EXECUTE, null); + } else { + if (log.isDebugEnabled()) { + log.debug(sm.getString("stream.inputBuffer.signal")); + } + synchronized (inBuffer) { + inBuffer.notifyAll(); + } } + } finally { + readStateLock.unlock(); } } @@ -1286,8 +1305,13 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { @Override - final synchronized void insertReplayedBody(ByteChunk body) { - inBuffer = ByteBuffer.wrap(body.getBytes(), body.getOffset(), body.getLength()); + final void insertReplayedBody(ByteChunk body) { + readStateLock.lock(); + try { + inBuffer = ByteBuffer.wrap(body.getBytes(), body.getOffset(), body.getLength()); + } finally { + readStateLock.unlock(); + } } @@ -1297,11 +1321,14 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { // this is the initial window size set by Tomcat that the client // uses (i.e. the local setting is required here). int size = handler.getLocalSettings().getInitialWindowSize(); - synchronized (this) { + readStateLock.lock(); + try { if (inBuffer == null && !closed) { inBuffer = ByteBuffer.allocate(size); outBuffer = new byte[size]; } + } finally { + readStateLock.unlock(); } } } @@ -1328,8 +1355,11 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { @Override final void swallowUnread() throws IOException { - synchronized (this) { + readStateLock.lock(); + try { closed = true; + } finally { + readStateLock.unlock(); } if (inBuffer != null) { int unreadByteCount = 0; --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org