Author: markt
Date: Tue May 20 18:41:56 2014
New Revision: 1596360

URL: http://svn.apache.org/r1596360
Log:
Backport of r1575885
Better align 7.0.x with trunk to aid back-ports

Modified:
    tomcat/tc7.0.x/trunk/   (props changed)
    
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AbstractServletOutputStream.java

Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
  Merged /tomcat/trunk:r1575885

Modified: 
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AbstractServletOutputStream.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AbstractServletOutputStream.java?rev=1596360&r1=1596359&r2=1596360&view=diff
==============================================================================
--- 
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AbstractServletOutputStream.java
 (original)
+++ 
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AbstractServletOutputStream.java
 Tue May 20 18:41:56 2014
@@ -32,14 +32,29 @@ public abstract class AbstractServletOut
     protected static final StringManager sm =
             StringManager.getManager(Constants.Package);
 
+    // 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;
 
     /**
@@ -152,26 +167,26 @@ 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);
             }
         }
     }
@@ -194,7 +209,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-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to