You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2014/03/10 11:15:55 UTC

svn commit: r1575885 - /tomcat/trunk/java/org/apache/coyote/http11/upgrade/AbstractServletOutputStream.java

Author: markt
Date: Mon Mar 10 10:15:54 2014
New Revision: 1575885

URL: http://svn.apache.org/r1575885
Log:
Add more comments to explain the locks.
Reduce scope of the writeLock in onWritePossible

Modified:
    tomcat/trunk/java/org/apache/coyote/http11/upgrade/AbstractServletOutputStream.java

Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/AbstractServletOutputStream.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/AbstractServletOutputStream.java?rev=1575885&r1=1575884&r2=1575885&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/upgrade/AbstractServletOutputStream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/AbstractServletOutputStream.java Mon Mar 10 10:15:54 2014
@@ -33,14 +33,29 @@ public abstract class AbstractServletOut
 
     protected final SocketWrapper<S> socketWrapper;
 
+    // Used to ensure that isReady() and onWritePossible() have a consistent
+    // view of buffer and fireListener when determining if the listener should
+    // fire.
     private final Object fireListenerLock = new Object();
+
+    // Used to ensure that only one thread writes to the socket at a time and
+    // that buffer is consistently updated with any unwritten data after the
+    // write. Note it is not necessary to hold this lock when checking if buffer
+    // contains data but, depending on how the result is used, some form of
+    // synchronization may be required (see fireListenerLock for an example).
     private final Object writeLock = new Object();
 
     private volatile boolean closeRequired = false;
+
     // Start in blocking-mode
     private volatile WriteListener listener = null;
+
+    // Guarded by fireListenerLock
     private volatile boolean fireListener = false;
+
     private volatile ClassLoader applicationLoader = null;
+
+    // Writes guarded by writeLock
     private volatile byte[] buffer;
 
 
@@ -168,27 +183,27 @@ public abstract class AbstractServletOut
                     throw new IOException(t);
                 }
             }
+        }
 
-            // Make sure isReady() and onWritePossible() have a consistent view
-            // of buffer and fireListener when determining if the listener
-            // should fire
-            boolean fire = false;
-
-            synchronized (fireListenerLock) {
-                if (buffer == null && fireListener) {
-                    fireListener = false;
-                    fire = true;
-                }
+        // Make sure isReady() and onWritePossible() have a consistent view
+        // of buffer and fireListener when determining if the listener
+        // should fire
+        boolean fire = false;
+        synchronized (fireListenerLock) {
+            if (buffer == null && fireListener) {
+                fireListener = false;
+                fire = true;
             }
-            if (fire) {
-                Thread thread = Thread.currentThread();
-                ClassLoader originalClassLoader = thread.getContextClassLoader();
-                try {
-                    thread.setContextClassLoader(applicationLoader);
-                    listener.onWritePossible();
-                } finally {
-                    thread.setContextClassLoader(originalClassLoader);
-                }
+        }
+
+        if (fire) {
+            Thread thread = Thread.currentThread();
+            ClassLoader originalClassLoader = thread.getContextClassLoader();
+            try {
+                thread.setContextClassLoader(applicationLoader);
+                listener.onWritePossible();
+            } finally {
+                thread.setContextClassLoader(originalClassLoader);
             }
         }
     }
@@ -212,7 +227,8 @@ public abstract class AbstractServletOut
     /**
      * Abstract method to be overridden by concrete implementations. The base
      * class will ensure that there are no concurrent calls to this method for
-     * the same socket.
+     * the same socket by ensuring that the writeLock is held when making any
+     * calls this method.
      */
     protected abstract int doWrite(boolean block, byte[] b, int off, int len)
             throws IOException;



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org