This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/10.1.x by this push:
new 24b8501020 Refactor to reduce pinning in HTTP/2 code when using
virtual threads
24b8501020 is described below
commit 24b8501020eac62dbfe6957887aa8c2e1e0f803d
Author: Mark Thomas <[email protected]>
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 88056547fa..b0dd8ad844 100644
--- a/java/org/apache/coyote/http2/Stream.java
+++ b/java/org/apache/coyote/http2/Stream.java
@@ -1155,6 +1155,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
@@ -1265,7 +1266,8 @@ class Stream extends AbstractNonZeroStream implements
HeaderEmitter {
final boolean isReadyForRead() {
ensureBuffersExist();
- synchronized (this) {
+ readStateLock.lock();
+ try {
if (available() > 0) {
return true;
}
@@ -1275,21 +1277,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();
}
@@ -1297,26 +1311,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();
}
}
@@ -1329,8 +1348,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();
+ }
}
@@ -1340,11 +1364,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();
}
}
}
@@ -1371,8 +1398,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: [email protected]
For additional commands, e-mail: [email protected]