Author: markt
Date: Tue Jun 12 12:40:00 2012
New Revision: 1349300
URL: http://svn.apache.org/viewvc?rev=1349300&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=52999
Remove synchronization bottleneck in container event handling
Modified:
tomcat/tc7.0.x/trunk/ (props changed)
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ContainerBase.java
tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
Merged /tomcat/trunk:r1349298
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ContainerBase.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ContainerBase.java?rev=1349300&r1=1349299&r2=1349300&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ContainerBase.java
(original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ContainerBase.java Tue
Jun 12 12:40:00 2012
@@ -178,7 +178,9 @@ public abstract class ContainerBase exte
/**
* The container event listeners for this Container.
*/
- protected ArrayList<ContainerListener> listeners = new
ArrayList<ContainerListener>();
+ protected ArrayList<ContainerListener> listeners =
+ new ArrayList<ContainerListener>();
+ protected ReadWriteLock listenersLock = new ReentrantReadWriteLock();
/**
@@ -914,10 +916,13 @@ public abstract class ContainerBase exte
@Override
public void addContainerListener(ContainerListener listener) {
- synchronized (listeners) {
+ Lock write = listenersLock.writeLock();
+ write.lock();
+ try {
listeners.add(listener);
+ } finally {
+ write.unlock();
}
-
}
@@ -975,12 +980,15 @@ public abstract class ContainerBase exte
@Override
public ContainerListener[] findContainerListeners() {
- synchronized (listeners) {
+ Lock read = listenersLock.readLock();
+ read.lock();
+ try {
ContainerListener[] results =
new ContainerListener[listeners.size()];
return listeners.toArray(results);
+ } finally {
+ read.unlock();
}
-
}
@@ -1059,10 +1067,13 @@ public abstract class ContainerBase exte
@Override
public void removeContainerListener(ContainerListener listener) {
- synchronized (listeners) {
+ Lock write = listenersLock.writeLock();
+ write.lock();
+ try {
listeners.remove(listener);
+ } finally {
+ write.unlock();
}
-
}
@@ -1397,16 +1408,31 @@ public abstract class ContainerBase exte
@Override
public void fireContainerEvent(String type, Object data) {
- if (listeners.size() < 1)
- return;
- ContainerEvent event = new ContainerEvent(this, type, data);
- ContainerListener list[] = new ContainerListener[0];
- synchronized (listeners) {
- list = listeners.toArray(list);
+ /*
+ * Implementation note
+ * There are two options here.
+ * 1) Take a copy of listeners and fire the events outside of the read
+ * lock
+ * 2) Don't take a copy and fire the events inside the read lock
+ *
+ * Approach 2 has been used here since holding the read lock only
+ * prevents writes and that is preferable to creating lots of array
+ * objects. Since writes occur on start / stop (unless an external
+ * management tool is used) then holding the read lock for a relatively
+ * long time should not be an issue.
+ */
+ Lock read = listenersLock.readLock();
+ read.lock();
+ try {
+ if (listeners.size() < 1)
+ return;
+ ContainerEvent event = new ContainerEvent(this, type, data);
+ for (ContainerListener listener : listeners) {
+ listener.containerEvent(event);
+ }
+ } finally {
+ read.unlock();
}
- for (int i = 0; i < list.length; i++)
- list[i].containerEvent(event);
-
}
Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1349300&r1=1349299&r2=1349300&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Tue Jun 12 12:40:00 2012
@@ -65,6 +65,10 @@
start-stop thread pool. It allows to use daemon threads and give
them more distinct names. (kfujino)
</update>
+ <fix>
+ <bug>52999</bug>: Remove synchronization bottleneck from the firing of
+ <code>Container</code> events. (markt)
+ </fix>
<add>
<bug>53008</bug>: Additional test cases for BASIC authentication and
RFC2617 compliance. Patch provided by Brian Burch. (markt)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]