This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH]: Channels and IllegalBlockingModeException


Hi Michael,

>> On the other hand, I now have inIOOperation in two places:
>> ServerSocketChannelImpl and SocketChannelImpl. I think I
>> can move this to PlainSocketImpl and avoid the duplication.
>> What do you think? (Remember that SocketChannelImpl and
>> ServerSocketChannelImpl <i>must</i> use PlainSocketImpl
>> and are not allowed to have a custom implementation.)
>
>Sounds like the right way.

This is my official submission of this:

http://gcc.gnu.org/ml/java-patches/2004-q1/msg00367.html

...with the refactoring I mentioned above to put the "in channels
operation" indicator in PlainSocketImpl instead of in both
SocketChannelImpl and ServerSocketChannelImpl.

This passes my tests.

I didn't put " (" in any new code I wrote, but I also didn't
change it in old code which I simply indented which shows
up as new code in the diff.

I did and tested this against the trunk and I'm okay with it.
Can you look at this one more time?

-- Mohan
http://www.thisiscool.com/
http://www.animalsong.org/

ChangeLog
2004-01-29  Mohan Embar  <gnustuff@thisiscool.com>

	* gnu/java/net/PlainSocketImpl.java 
	(inChannelOperation): New field.
	(isInChannelOperation): New accessor.
	(setInChannelOperation): New modifier.
	* gnu/java/nio/ServerSocketChannelImpl.java
	(accept): Set and reset our server socket's PlainSocketImpl's
	"in channel operation" indicator before and after delegating
	the accept to our server socket.
	* gnu/java/nio/SocketChannelImpl.java
	(connect): Set and reset our socket's PlainSocketImpl's "in channel
	operation" indicator before and after delegating the operation to
	our socket.
	(read): Likewise.
	(write): Likewise.
	* java/net/ServerSocket.java (implAccept): Don't throw an
	IllegalBlockingModeException if we have a non-blocking
	channel which initiated this accept operation.
	* java/net/Socket.java (connect): Don't throw an
	IllegalBlockingModeException if we have a non-blocking
	channel which initiated this connect operation.
	* java/nio/channels/spi/AbstractSelectableChannel.java
	(configureBlocking): Only call implConfigureBlocking() if
	the desired blocking mode is different from our current one.

Index: gnu/java/net/PlainSocketImpl.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/net/PlainSocketImpl.java,v
retrieving revision 1.4
diff -u -2 -r1.4 PlainSocketImpl.java
--- gnu/java/net/PlainSocketImpl.java	21 Oct 2003 12:29:43 -0000	1.4
+++ gnu/java/net/PlainSocketImpl.java	30 Jan 2004 01:38:19 -0000
@@ -121,4 +121,31 @@
 
   /**
+   * Indicates whether a channel initiated whatever operation
+   * is being invoked on this socket.
+   */
+  private boolean inChannelOperation;
+
+  /**
+   * Indicates whether we should ignore whether any associated
+   * channel is set to non-blocking mode. Certain operations
+   * throw an <code>IllegalBlockingModeException</code> if the
+   * associated channel is in non-blocking mode, <i>except</i>
+   * if the operation is invoked by the channel itself.
+   */
+  public final boolean isInChannelOperation()
+  {
+    return inChannelOperation;
+  }
+  
+  /**
+   * Sets our indicator of whether an I/O operation is being
+   * initiated by a channel.
+   */
+  public final void setInChannelOperation(boolean b)
+  {
+    inChannelOperation = b;
+  }
+ 
+  /**
    * Default do nothing constructor
    */
Index: gnu/java/nio/ServerSocketChannelImpl.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/nio/ServerSocketChannelImpl.java,v
retrieving revision 1.11
diff -u -2 -r1.11 ServerSocketChannelImpl.java
--- gnu/java/nio/ServerSocketChannelImpl.java	7 Jan 2004 16:51:49 -0000	1.11
+++ gnu/java/nio/ServerSocketChannelImpl.java	30 Jan 2004 01:38:20 -0000
@@ -70,5 +70,5 @@
     return serverSocket.getPlainSocketImpl().getNativeFD();
   }
- 
+  
   public void finalizer()
   {
@@ -108,4 +108,9 @@
     try
       {
+        begin();
+        serverSocket.getPlainSocketImpl().setInChannelOperation(true);
+          // indicate that a channel is initiating the accept operation
+          // so that the socket ignores the fact that we might be in
+          // non-blocking mode.
         NIOSocket socket = (NIOSocket) serverSocket.accept();
         completed = true;
@@ -118,4 +123,5 @@
     finally
       {
+        serverSocket.getPlainSocketImpl().setInChannelOperation(false);
         end (completed);
       }
Index: gnu/java/nio/SocketChannelImpl.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/nio/SocketChannelImpl.java,v
retrieving revision 1.15
diff -u -2 -r1.15 SocketChannelImpl.java
--- gnu/java/nio/SocketChannelImpl.java	7 Jan 2004 16:51:49 -0000	1.15
+++ gnu/java/nio/SocketChannelImpl.java	30 Jan 2004 01:38:20 -0000
@@ -137,21 +137,33 @@
       throw new UnresolvedAddressException();
     
-    if (isBlocking())
-      {
-        // Do blocking connect.
-        socket.connect (remote);
-        return true;
-      }
-
-    // Do non-blocking connect.
     try
       {
-        socket.connect (remote, NIOConstants.DEFAULT_TIMEOUT);
-        return true;
+        socket.getPlainSocketImpl().setInChannelOperation(true);
+          // indicate that a channel is initiating the accept operation
+          // so that the socket ignores the fact that we might be in
+          // non-blocking mode.
+        
+        if (isBlocking())
+          {
+            // Do blocking connect.
+            socket.connect (remote);
+            return true;
+          }
+
+        // Do non-blocking connect.
+        try
+          {
+            socket.connect (remote, NIOConstants.DEFAULT_TIMEOUT);
+            return true;
+          }
+        catch (SocketTimeoutException e)
+          {
+            connectionPending = true;
+            return false;
+          }
       }
-    catch (SocketTimeoutException e)
+    finally
       {
-        connectionPending = true;
-        return false;
+        socket.getPlainSocketImpl().setInChannelOperation(false);
       }
   }
@@ -239,4 +251,5 @@
       {
         begin();
+        socket.getPlainSocketImpl().setInChannelOperation(true);
         readBytes = input.read (data, offset, len);
         completed = true;
@@ -245,4 +258,5 @@
       {
         end (completed);
+        socket.getPlainSocketImpl().setInChannelOperation(false);
       }
 
@@ -302,5 +316,18 @@
 
     OutputStream output = socket.getOutputStream();
-    output.write (data, offset, len);
+    boolean completed = false;
+
+    try
+      {
+        begin();
+        socket.getPlainSocketImpl().setInChannelOperation(true);
+        output.write (data, offset, len);
+        completed = true;
+      }
+    finally
+      {
+        end (completed);
+        socket.getPlainSocketImpl().setInChannelOperation(false);
+      }
 
     if (src.hasArray())
Index: java/net/ServerSocket.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/net/ServerSocket.java,v
retrieving revision 1.34
diff -u -2 -r1.34 ServerSocket.java
--- java/net/ServerSocket.java	7 Jan 2004 16:37:45 -0000	1.34
+++ java/net/ServerSocket.java	30 Jan 2004 01:38:23 -0000
@@ -346,7 +346,12 @@
       throw new SocketException("ServerSocket is closed");
     
+    // The Sun spec says that if we have an associated channel and
+    // it is in non-blocking mode, we throw an IllegalBlockingModeException.
+    // However, in our implementation if the channel itself initiated this
+    // operation, then we must honor it regardless of its blocking mode.
     if (getChannel() != null
-        && !getChannel().isBlocking())
-      throw new IllegalBlockingModeException();
+        && !getChannel().isBlocking ()
+        && !((PlainSocketImpl) getImpl()).isInChannelOperation())
+      throw new IllegalBlockingModeException ();
 	    
     impl.accept(socket.getImpl());
Index: java/net/Socket.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/net/Socket.java,v
retrieving revision 1.33
diff -u -2 -r1.33 Socket.java
--- java/net/Socket.java	9 Dec 2003 15:39:23 -0000	1.33
+++ java/net/Socket.java	30 Jan 2004 01:38:24 -0000
@@ -421,6 +421,11 @@
       throw new IllegalArgumentException("unsupported address type");
 
+    // The Sun spec says that if we have an associated channel and
+    // it is in non-blocking mode, we throw an IllegalBlockingModeException.
+    // However, in our implementation if the channel itself initiated this
+    // operation, then we must honor it regardless of its blocking mode.
     if (getChannel() != null
-        && !getChannel().isBlocking ())
+        && !getChannel().isBlocking ()
+        && !((PlainSocketImpl) getImpl()).isInChannelOperation())
       throw new IllegalBlockingModeException ();
   
Index: java/nio/channels/spi/AbstractSelectableChannel.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/nio/channels/spi/AbstractSelectableChannel.java,v
retrieving revision 1.7
diff -u -2 -r1.7 AbstractSelectableChannel.java
--- java/nio/channels/spi/AbstractSelectableChannel.java	7 Jan 2004 16:51:49 -0000	1.7
+++ java/nio/channels/spi/AbstractSelectableChannel.java	30 Jan 2004 01:38:24 -0000
@@ -81,6 +81,9 @@
     synchronized (blockingLock())
       {
-        implConfigureBlocking(blocking);
-        this.blocking = blocking;
+        if (this.blocking != blocking)
+          {
+            implConfigureBlocking(blocking);
+            this.blocking = blocking;
+          }
       }
     





Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]