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

Reply via email to