You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2008/12/08 20:38:58 UTC

svn commit: r724457 - /httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/IOSessionImpl.java

Author: olegk
Date: Mon Dec  8 11:38:58 2008
New Revision: 724457

URL: http://svn.apache.org/viewvc?rev=724457&view=rev
Log:
* Use dedicated mutex for critical section around interestOps operations
* Minimize contention for SelectionKey to reduce possibility of a deadlock
* Added protected methods that can be overridden by a super classes in order to change handling of SelectionKey#interestOps

Modified:
    httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/IOSessionImpl.java

Modified: httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/IOSessionImpl.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/IOSessionImpl.java?rev=724457&r1=724456&r2=724457&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/IOSessionImpl.java (original)
+++ httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/IOSessionImpl.java Mon Dec  8 11:38:58 2008
@@ -36,6 +36,7 @@
 import java.nio.channels.ByteChannel;
 import java.nio.channels.Channel;
 import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
 import java.nio.channels.SocketChannel;
 import java.util.Collections;
 import java.util.HashMap;
@@ -49,9 +50,11 @@
     private volatile int status;
     
     private final SelectionKey key;
+    private final Selector selector;
     private final ByteChannel channel;
     private final SessionClosedCallback callback;
     private final Map<String, Object> attributes;
+    private final Object mutex;
     
     private volatile int interestOps;
     private SessionBufferStatus bufferStatus;
@@ -63,9 +66,11 @@
             throw new IllegalArgumentException("Selection key may not be null");
         }
         this.key = key;
-        this.channel = (ByteChannel) this.key.channel();
+        this.selector = key.selector();
+        this.channel = (ByteChannel) key.channel();
         this.callback = callback;
         this.attributes = Collections.synchronizedMap(new HashMap<String, Object>());
+        this.mutex = new Object();
         this.interestOps = key.interestOps();
         this.socketTimeout = 0;
         this.status = ACTIVE;
@@ -76,7 +81,7 @@
     }
     
     public SocketAddress getLocalAddress() {
-        Channel channel = this.key.channel();
+        Channel channel = this.channel;
         if (channel instanceof SocketChannel) {
             return ((SocketChannel)channel).socket().getLocalSocketAddress();
         } else {
@@ -85,7 +90,7 @@
     }
 
     public SocketAddress getRemoteAddress() {
-        Channel channel = this.key.channel();
+        Channel channel = this.channel;
         if (channel instanceof SocketChannel) {
             return ((SocketChannel)channel).socket().getRemoteSocketAddress();
         } else {
@@ -101,33 +106,41 @@
         if (this.status == CLOSED) {
             return;
         }
-        synchronized (this.key) {
+        synchronized (this.mutex) {
             this.interestOps = ops;
-            this.key.interestOps(ops);
+            interestOpsChanged();
         }
-        this.key.selector().wakeup();
+        this.selector.wakeup();
     }
     
     public void setEvent(int op) {
         if (this.status == CLOSED) {
             return;
         }
-        synchronized (this.key) {
+        synchronized (this.mutex) {
             this.interestOps = this.interestOps | op;
-            this.key.interestOps(this.interestOps);
+            interestOpsChanged();
         }
-        this.key.selector().wakeup();
+        this.selector.wakeup();
     }
     
     public void clearEvent(int op) {
         if (this.status == CLOSED) {
             return;
         }
-        synchronized (this.key) {
+        synchronized (this.mutex) {
             this.interestOps = this.interestOps & ~op;
-            this.key.interestOps(this.interestOps);
+            interestOpsChanged();
         }
-        this.key.selector().wakeup();
+        this.selector.wakeup();
+    }
+    
+    protected void interestOpsChanged() {
+        applyInterestOps();
+    }
+    
+    protected void applyInterestOps() {
+        this.key.interestOps(this.interestOps);
     }
     
     public int getSocketTimeout() {
@@ -145,7 +158,7 @@
         this.status = CLOSED;
         this.key.cancel();
         try {
-            this.key.channel().close();
+            this.channel.close();
         } catch (IOException ex) {
             // Munching exceptions is not nice
             // but in this case it is justified
@@ -153,8 +166,8 @@
         if (this.callback != null) {
             this.callback.sessionClosed(this);
         }
-        if (this.key.selector().isOpen()) {
-            this.key.selector().wakeup();
+        if (this.selector.isOpen()) {
+            this.selector.wakeup();
         }
     }