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: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org