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: [email protected]
For additional commands, e-mail: [email protected]