You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by tr...@apache.org on 2007/06/07 12:02:37 UTC
svn commit: r545135 - in /mina/trunk/core/src:
main/java/org/apache/mina/common/support/DefaultIoFuture.java
test/java/org/apache/mina/common/support/FutureTest.java
Author: trustin
Date: Thu Jun 7 03:02:36 2007
New Revision: 545135
URL: http://svn.apache.org/viewvc?view=rev&rev=545135
Log:
Resolved issue: DIRMINA-377 (Reduce memory consumption of DefaultIoFuture)
* Minimized memory consumption by allocating a special member variable for the first listener.
* Applied additional (experimental) optimization to trunk
Modified:
mina/trunk/core/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java
mina/trunk/core/src/test/java/org/apache/mina/common/support/FutureTest.java
Modified: mina/trunk/core/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java?view=diff&rev=545135&r1=545134&r2=545135
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java Thu Jun 7 03:02:36 2007
@@ -37,7 +37,8 @@
{
private final IoSession session;
private final Object lock;
- private final List<IoFutureListener> listeners = new ArrayList<IoFutureListener>();
+ private IoFutureListener firstListener;
+ private List<IoFutureListener> otherListeners;
private Object result;
private boolean ready;
@@ -179,9 +180,9 @@
result = newValue;
ready = true;
lock.notifyAll();
-
- notifyListeners();
}
+
+ notifyListeners();
}
/**
@@ -202,15 +203,25 @@
throw new NullPointerException( "listener" );
}
- synchronized( lock )
- {
- listeners.add( listener );
- if( ready )
- {
- listener.operationComplete( this );
+ boolean notifyNow = false;
+ synchronized (lock) {
+ if (ready) {
+ notifyNow = true;
+ } else {
+ if (firstListener == null) {
+ firstListener = listener;
+ } else {
+ if (otherListeners == null) {
+ otherListeners = new ArrayList<IoFutureListener>(1);
+ }
+ otherListeners.add(listener);
+ }
}
}
+ if (notifyNow) {
+ listener.operationComplete( this );
+ }
return this;
}
@@ -223,7 +234,15 @@
synchronized( lock )
{
- listeners.remove( listener );
+ if (!ready) {
+ if (listener == firstListener) {
+ if (otherListeners != null && !otherListeners.isEmpty()) {
+ firstListener = otherListeners.remove(0);
+ }
+ } else if (otherListeners != null) {
+ otherListeners.remove(listener);
+ }
+ }
}
return this;
@@ -231,10 +250,18 @@
private void notifyListeners()
{
- synchronized( lock )
- {
- for (IoFutureListener l : listeners) {
- l.operationComplete( this );
+ // There won't be any visibility problem or concurrent modification
+ // because 'ready' flag will be checked against both addListener and
+ // removeListener calls.
+ if (firstListener != null) {
+ firstListener.operationComplete(this);
+ firstListener = null;
+
+ if (otherListeners != null) {
+ for (IoFutureListener l : otherListeners) {
+ l.operationComplete( this );
+ }
+ otherListeners = null;
}
}
}
Modified: mina/trunk/core/src/test/java/org/apache/mina/common/support/FutureTest.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/test/java/org/apache/mina/common/support/FutureTest.java?view=diff&rev=545135&r1=545134&r2=545135
==============================================================================
--- mina/trunk/core/src/test/java/org/apache/mina/common/support/FutureTest.java (original)
+++ mina/trunk/core/src/test/java/org/apache/mina/common/support/FutureTest.java Thu Jun 7 03:02:36 2007
@@ -26,6 +26,7 @@
import org.apache.mina.common.IoFilterChain;
import org.apache.mina.common.IoFuture;
+import org.apache.mina.common.IoFutureListener;
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoService;
import org.apache.mina.common.IoSession;
@@ -192,6 +193,100 @@
assertFalse( future.isWritten() );
}
+ public void testAddListener() throws Exception {
+ DefaultCloseFuture future = new DefaultCloseFuture( null );
+ assertFalse( future.isReady() );
+ assertFalse( future.isClosed() );
+
+ TestListener listener1 = new TestListener();
+ TestListener listener2 = new TestListener();
+ future.addListener(listener1);
+ future.addListener(listener2);
+
+ TestThread thread = new TestThread( future );
+ thread.start();
+
+ future.setClosed();
+ thread.join();
+
+ assertTrue( thread.success );
+ assertTrue( future.isReady() );
+ assertTrue( future.isClosed() );
+
+ assertSame( future, listener1.notifiedFuture );
+ assertSame( future, listener2.notifiedFuture );
+ }
+
+ public void testLateAddListener() throws Exception {
+ DefaultCloseFuture future = new DefaultCloseFuture( null );
+ assertFalse( future.isReady() );
+ assertFalse( future.isClosed() );
+
+ TestThread thread = new TestThread( future );
+ thread.start();
+
+ future.setClosed();
+ thread.join();
+
+ assertTrue( thread.success );
+ assertTrue( future.isReady() );
+ assertTrue( future.isClosed() );
+
+ TestListener listener = new TestListener();
+ future.addListener(listener);
+ assertSame( future, listener.notifiedFuture );
+ }
+
+ public void testRemoveListener1() throws Exception {
+ DefaultCloseFuture future = new DefaultCloseFuture( null );
+ assertFalse( future.isReady() );
+ assertFalse( future.isClosed() );
+
+ TestListener listener1 = new TestListener();
+ TestListener listener2 = new TestListener();
+ future.addListener(listener1);
+ future.addListener(listener2);
+ future.removeListener(listener1);
+
+ TestThread thread = new TestThread( future );
+ thread.start();
+
+ future.setClosed();
+ thread.join();
+
+ assertTrue( thread.success );
+ assertTrue( future.isReady() );
+ assertTrue( future.isClosed() );
+
+ assertSame( null, listener1.notifiedFuture );
+ assertSame( future, listener2.notifiedFuture );
+ }
+
+ public void testRemoveListener2() throws Exception {
+ DefaultCloseFuture future = new DefaultCloseFuture( null );
+ assertFalse( future.isReady() );
+ assertFalse( future.isClosed() );
+
+ TestListener listener1 = new TestListener();
+ TestListener listener2 = new TestListener();
+ future.addListener(listener1);
+ future.addListener(listener2);
+ future.removeListener(listener2);
+
+ TestThread thread = new TestThread( future );
+ thread.start();
+
+ future.setClosed();
+ thread.join();
+
+ assertTrue( thread.success );
+ assertTrue( future.isReady() );
+ assertTrue( future.isClosed() );
+
+ assertSame( future, listener1.notifiedFuture );
+ assertSame( null, listener2.notifiedFuture );
+ }
+
private static class TestThread extends Thread
{
private final IoFuture future;
@@ -206,6 +301,14 @@
public void run()
{
success = future.awaitUninterruptibly( 10000 );
+ }
+ }
+
+ private static class TestListener implements IoFutureListener {
+ private IoFuture notifiedFuture;
+
+ public void operationComplete(IoFuture future) {
+ this.notifiedFuture = future;
}
}
}