Repository: netty/netty
Issue: Allow specifying `SelectorProvider` when constructing an NIO channel
Labels: feature

When constructing an `NioEventLoop(Group)` a user can specify his/her preferred `SelectorProvider`, but we do not allow doing that when constructing an NIO channel.  For example, you cannot specify your preferred `SelectorProvider` when constructing an `NioSocketChannel`, which makes using an alternative `SelectorProvider` practically useless.


Issue comments:
I think that it may be closed too


Pull request review comments:

Patch that resolved the issue:
diff --git a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java
index 3feef9283e1..aa71a8b7467 100644
--- a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java
+++ b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java
@@ -61,7 +61,7 @@ public final class NioDatagramChannel
         extends AbstractNioMessageChannel implements io.netty.channel.socket.DatagramChannel {
 
     private static final ChannelMetadata METADATA = new ChannelMetadata(true);
-    private static final SelectorProvider SELECTOR_PROVIDER = SelectorProvider.provider();
+    private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
 
     private final DatagramChannelConfig config;
     private final Map<InetAddress, List<MembershipKey>> memberships =
@@ -69,7 +69,7 @@ public final class NioDatagramChannel
 
     private RecvByteBufAllocator.Handle allocHandle;
 
-    private static DatagramChannel newSocket() {
+    private static DatagramChannel newSocket(SelectorProvider provider) {
         try {
             /**
              *  Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
@@ -77,21 +77,21 @@ private static DatagramChannel newSocket() {
              *
              *  See <a href="See https://github.com/netty/netty/issues/2308">#2308</a>.
              */
-            return SELECTOR_PROVIDER.openDatagramChannel();
+            return provider.openDatagramChannel();
         } catch (IOException e) {
             throw new ChannelException("Failed to open a socket.", e);
         }
     }
 
-    private static DatagramChannel newSocket(InternetProtocolFamily ipFamily) {
+    private static DatagramChannel newSocket(SelectorProvider provider, InternetProtocolFamily ipFamily) {
         if (ipFamily == null) {
-            return newSocket();
+            return newSocket(provider);
         }
 
         checkJavaVersion();
 
         try {
-            return SELECTOR_PROVIDER.openDatagramChannel(ProtocolFamilyConverter.convert(ipFamily));
+            return provider.openDatagramChannel(ProtocolFamilyConverter.convert(ipFamily));
         } catch (IOException e) {
             throw new ChannelException("Failed to open a socket.", e);
         }
@@ -107,7 +107,15 @@ private static void checkJavaVersion() {
      * Create a new instance which will use the Operation Systems default {@link InternetProtocolFamily}.
      */
     public NioDatagramChannel() {
-        this(newSocket());
+        this(newSocket(DEFAULT_SELECTOR_PROVIDER));
+    }
+
+    /**
+     * Create a new instance using the given {@link SelectorProvider}
+     * which will use the Operation Systems default {@link InternetProtocolFamily}.
+     */
+    public NioDatagramChannel(SelectorProvider provider) {
+        this(newSocket(provider));
     }
 
     /**
@@ -115,7 +123,16 @@ public NioDatagramChannel() {
      * on the Operation Systems default which will be chosen.
      */
     public NioDatagramChannel(InternetProtocolFamily ipFamily) {
-        this(newSocket(ipFamily));
+        this(newSocket(DEFAULT_SELECTOR_PROVIDER, ipFamily));
+    }
+
+    /**
+     * Create a new instance using the given {@link SelectorProvider} and {@link InternetProtocolFamily}.
+     * If {@link InternetProtocolFamily} is {@code null} it will depend on the Operation Systems default
+     * which will be chosen.
+     */
+    public NioDatagramChannel(SelectorProvider provider, InternetProtocolFamily ipFamily) {
+        this(newSocket(provider, ipFamily));
     }
 
     /**
diff --git a/transport/src/main/java/io/netty/channel/socket/nio/NioServerSocketChannel.java b/transport/src/main/java/io/netty/channel/socket/nio/NioServerSocketChannel.java
index 32382018715..d6751727c94 100644
--- a/transport/src/main/java/io/netty/channel/socket/nio/NioServerSocketChannel.java
+++ b/transport/src/main/java/io/netty/channel/socket/nio/NioServerSocketChannel.java
@@ -41,11 +41,11 @@ public class NioServerSocketChannel extends AbstractNioMessageChannel
                              implements io.netty.channel.socket.ServerSocketChannel {
 
     private static final ChannelMetadata METADATA = new ChannelMetadata(false);
-    private static final SelectorProvider SELECTOR_PROVIDER = SelectorProvider.provider();
+    private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
 
     private static final InternalLogger logger = InternalLoggerFactory.getInstance(NioServerSocketChannel.class);
 
-    private static ServerSocketChannel newSocket() {
+    private static ServerSocketChannel newSocket(SelectorProvider provider) {
         try {
             /**
              *  Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
@@ -53,7 +53,7 @@ private static ServerSocketChannel newSocket() {
              *
              *  See <a href="See https://github.com/netty/netty/issues/2308">#2308</a>.
              */
-            return SELECTOR_PROVIDER.openServerSocketChannel();
+            return provider.openServerSocketChannel();
         } catch (IOException e) {
             throw new ChannelException(
                     "Failed to open a server socket.", e);
@@ -66,7 +66,14 @@ private static ServerSocketChannel newSocket() {
      * Create a new instance
      */
     public NioServerSocketChannel() {
-        this(newSocket());
+        this(newSocket(DEFAULT_SELECTOR_PROVIDER));
+    }
+
+    /**
+     * Create a new instance using the given {@link SelectorProvider}.
+     */
+    public NioServerSocketChannel(SelectorProvider provider) {
+        this(newSocket(provider));
     }
 
     /**
diff --git a/transport/src/main/java/io/netty/channel/socket/nio/NioSocketChannel.java b/transport/src/main/java/io/netty/channel/socket/nio/NioSocketChannel.java
index d0e046c10a4..ea45f24d09d 100644
--- a/transport/src/main/java/io/netty/channel/socket/nio/NioSocketChannel.java
+++ b/transport/src/main/java/io/netty/channel/socket/nio/NioSocketChannel.java
@@ -44,9 +44,9 @@
 public class NioSocketChannel extends AbstractNioByteChannel implements io.netty.channel.socket.SocketChannel {
 
     private static final ChannelMetadata METADATA = new ChannelMetadata(false);
-    private static final SelectorProvider SELECTOR_PROVIDER = SelectorProvider.provider();
+    private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
 
-    private static SocketChannel newSocket() {
+    private static SocketChannel newSocket(SelectorProvider provider) {
         try {
             /**
              *  Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
@@ -54,7 +54,7 @@ private static SocketChannel newSocket() {
              *
              *  See <a href="See https://github.com/netty/netty/issues/2308">#2308</a>.
              */
-            return SELECTOR_PROVIDER.openSocketChannel();
+            return provider.openSocketChannel();
         } catch (IOException e) {
             throw new ChannelException("Failed to open a socket.", e);
         }
@@ -66,7 +66,14 @@ private static SocketChannel newSocket() {
      * Create a new instance
      */
     public NioSocketChannel() {
-        this(newSocket());
+        this(newSocket(DEFAULT_SELECTOR_PROVIDER));
+    }
+
+    /**
+     * Create a new instance using the given {@link SelectorProvider}.
+     */
+    public NioSocketChannel(SelectorProvider provider) {
+        this(newSocket(provider));
     }
 
     /**


Test patch: