From e2bebc3072d52816ff7265d9a04d8f02948faa8e Mon Sep 17 00:00:00 2001 From: Wayne Meissner Date: Sat, 31 Jan 2009 23:05:26 +1000 Subject: [PATCH] Make NativeSelectableChannel an interface and reparent NativeSocketChannel and NativeDeviceChannel --- .../nio/channels/NativeDeviceChannel.java | 19 ++----- .../nio/channels/NativeSelectableChannel.java | 55 +------------------ .../channels/NativeServerSocketChannel.java | 40 ++++++++++++++ .../nio/channels/NativeSocketChannel.java | 39 +++++++++++-- .../nio/channels/kqueue/KQSelectionKey.java | 10 +--- .../nio/channels/poll/PollSelectionKey.java | 10 +--- src/example/TCPServer.java | 33 ++++++----- 7 files changed, 99 insertions(+), 107 deletions(-) create mode 100644 src/enxio/nio/channels/NativeServerSocketChannel.java diff --git a/src/enxio/nio/channels/NativeDeviceChannel.java b/src/enxio/nio/channels/NativeDeviceChannel.java index 53d1c3d..62e57df 100644 --- a/src/enxio/nio/channels/NativeDeviceChannel.java +++ b/src/enxio/nio/channels/NativeDeviceChannel.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package enxio.nio.channels; @@ -12,25 +8,20 @@ import java.nio.channels.spi.AbstractSelectableChannel; import java.nio.channels.spi.SelectorProvider; -/** - * - * @author wayne - */ -public class NativeDeviceChannel extends AbstractSelectableChannel implements ByteChannel { +public class NativeDeviceChannel extends AbstractSelectableChannel implements ByteChannel, NativeSelectableChannel { private final int fd; private final int validOps; + public NativeDeviceChannel(int fd) { + this(NativeSelectorProvider.getInstance(), fd, SelectionKey.OP_READ | SelectionKey.OP_WRITE); + } public NativeDeviceChannel(SelectorProvider provider, int fd, int ops) { super(provider); this.fd = fd; this.validOps = ops; } - public static NativeSelectableChannel forDevice(int fd) { - return new NativeSelectableChannel(NativeSelectorProvider.getInstance(), fd, - SelectionKey.OP_READ | SelectionKey.OP_WRITE); - } - + @Override protected void implCloseSelectableChannel() throws IOException { Native.close(fd); diff --git a/src/enxio/nio/channels/NativeSelectableChannel.java b/src/enxio/nio/channels/NativeSelectableChannel.java index 346f10c..2d8241c 100644 --- a/src/enxio/nio/channels/NativeSelectableChannel.java +++ b/src/enxio/nio/channels/NativeSelectableChannel.java @@ -1,57 +1,8 @@ package enxio.nio.channels; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.ByteChannel; -import java.nio.channels.SelectionKey; -import java.nio.channels.spi.AbstractSelectableChannel; -import java.nio.channels.spi.SelectorProvider; +import java.nio.channels.Channel; -public class NativeSelectableChannel extends AbstractSelectableChannel - implements ByteChannel { +public interface NativeSelectableChannel extends Channel { - private final int fd; - private final int validOps; - - public NativeSelectableChannel(SelectorProvider provider, int fd, int ops) { - super(provider); - this.fd = fd; - this.validOps = ops; - } - public static NativeSelectableChannel forSocket(int fd) { - return new NativeSelectableChannel(NativeSelectorProvider.getInstance(), fd, - SelectionKey.OP_READ | SelectionKey.OP_WRITE | SelectionKey.OP_CONNECT | SelectionKey.OP_ACCEPT); - } - public static NativeSelectableChannel forServerSocket(int fd) { - return forSocket(fd); - } - public static NativeSelectableChannel forDevice(int fd) { - return new NativeSelectableChannel(NativeSelectorProvider.getInstance(), fd, - SelectionKey.OP_READ | SelectionKey.OP_WRITE); - } - - @Override - protected void implCloseSelectableChannel() throws IOException { - Native.close(fd); - } - - @Override - protected void implConfigureBlocking(boolean block) throws IOException { - Native.setBlocking(fd, block); - } - - @Override - public final int validOps() { - return validOps; - } - public final int getFD() { - return fd; - } - public int read(ByteBuffer dst) throws IOException { - return Native.read(fd, dst); - } - - public int write(ByteBuffer src) throws IOException { - return Native.write(fd, src); - } + public int getFD(); } diff --git a/src/enxio/nio/channels/NativeServerSocketChannel.java b/src/enxio/nio/channels/NativeServerSocketChannel.java new file mode 100644 index 0000000..e54b705 --- /dev/null +++ b/src/enxio/nio/channels/NativeServerSocketChannel.java @@ -0,0 +1,40 @@ + +package enxio.nio.channels; + +import java.io.IOException; +import java.nio.channels.SelectionKey; +import java.nio.channels.spi.AbstractSelectableChannel; +import java.nio.channels.spi.SelectorProvider; + +public class NativeServerSocketChannel extends AbstractSelectableChannel implements NativeSelectableChannel { + + private final int fd; + private final int validOps; + + public NativeServerSocketChannel(int fd) { + this(NativeSelectorProvider.getInstance(), fd, SelectionKey.OP_ACCEPT); + } + public NativeServerSocketChannel(SelectorProvider provider, int fd, int ops) { + super(provider); + this.fd = fd; + this.validOps = ops; + } + + @Override + protected void implCloseSelectableChannel() throws IOException { + Native.close(fd); + } + + @Override + protected void implConfigureBlocking(boolean block) throws IOException { + Native.setBlocking(fd, block); + } + + @Override + public final int validOps() { + return validOps; + } + public final int getFD() { + return fd; + } +} diff --git a/src/enxio/nio/channels/NativeSocketChannel.java b/src/enxio/nio/channels/NativeSocketChannel.java index cf4d7b7..37c913b 100644 --- a/src/enxio/nio/channels/NativeSocketChannel.java +++ b/src/enxio/nio/channels/NativeSocketChannel.java @@ -3,20 +3,48 @@ import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; import java.nio.channels.SelectionKey; +import java.nio.channels.spi.AbstractSelectableChannel; +import java.nio.channels.spi.SelectorProvider; -public class NativeSocketChannel extends NativeSelectableChannel { +public class NativeSocketChannel extends AbstractSelectableChannel + implements ByteChannel, NativeSelectableChannel { + + private final int fd; + private final int validOps; public NativeSocketChannel(int fd) { - this(fd, SelectionKey.OP_READ | SelectionKey.OP_WRITE); + this(NativeSelectorProvider.getInstance(), fd, SelectionKey.OP_READ | SelectionKey.OP_WRITE); } public NativeSocketChannel(int fd, int ops) { - super(NativeSelectorProvider.getInstance(), fd, ops); + this(NativeSelectorProvider.getInstance(), fd, ops); + } + NativeSocketChannel(SelectorProvider provider, int fd, int ops) { + super(provider); + this.fd = fd; + this.validOps = ops; + } + + @Override + protected void implCloseSelectableChannel() throws IOException { + Native.close(fd); } @Override + protected void implConfigureBlocking(boolean block) throws IOException { + Native.setBlocking(fd, block); + } + + @Override + public final int validOps() { + return validOps; + } + public final int getFD() { + return fd; + } public int read(ByteBuffer dst) throws IOException { - int n = super.read(dst); + int n = Native.read(fd, dst); switch (n) { case 0: return -1; @@ -27,8 +55,7 @@ public int read(ByteBuffer dst) throws IOException { } } - @Override public int write(ByteBuffer src) throws IOException { - return super.write(src); + return Native.write(fd, src); } } diff --git a/src/enxio/nio/channels/kqueue/KQSelectionKey.java b/src/enxio/nio/channels/kqueue/KQSelectionKey.java index b98f9a5..e5e0f33 100644 --- a/src/enxio/nio/channels/kqueue/KQSelectionKey.java +++ b/src/enxio/nio/channels/kqueue/KQSelectionKey.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package enxio.nio.channels.kqueue; @@ -12,10 +8,6 @@ import java.nio.channels.spi.AbstractSelectionKey; import enxio.nio.channels.NativeSelectableChannel; -/** - * - * @author wayne - */ class KQSelectionKey extends AbstractSelectionKey { private final KQSelector selector; private final NativeSelectableChannel channel; @@ -33,7 +25,7 @@ int getFD() { @Override public SelectableChannel channel() { - return channel; + return (SelectableChannel) channel; } @Override diff --git a/src/enxio/nio/channels/poll/PollSelectionKey.java b/src/enxio/nio/channels/poll/PollSelectionKey.java index 3d8c198..24fc6db 100644 --- a/src/enxio/nio/channels/poll/PollSelectionKey.java +++ b/src/enxio/nio/channels/poll/PollSelectionKey.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package enxio.nio.channels.poll; @@ -11,10 +7,6 @@ import java.nio.channels.spi.AbstractSelectionKey; import enxio.nio.channels.NativeSelectableChannel; -/** - * - * @author wayne - */ class PollSelectionKey extends AbstractSelectionKey { private final PollSelector selector; private final NativeSelectableChannel channel; @@ -39,7 +31,7 @@ int getFD() { @Override public SelectableChannel channel() { - return channel; + return (SelectableChannel) channel; } @Override diff --git a/src/example/TCPServer.java b/src/example/TCPServer.java index d5ea964..c066724 100644 --- a/src/example/TCPServer.java +++ b/src/example/TCPServer.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package example; @@ -19,6 +15,9 @@ import java.nio.channels.Selector; import enxio.nio.channels.NativeSelectableChannel; import enxio.nio.channels.NativeSelectorProvider; +import enxio.nio.channels.NativeServerSocketChannel; +import enxio.nio.channels.NativeSocketChannel; +import java.nio.channels.SelectableChannel; /** * @@ -60,7 +59,7 @@ private static interface LibC { static short htons(short val) { return Short.reverseBytes(val); } - static NativeSelectableChannel serverSocket(int port) { + static NativeServerSocketChannel serverSocket(int port) { int fd = libc.socket(LibC.AF_INET, LibC.SOCK_STREAM, 0); System.out.println("fd=" + fd); SockAddr addr; @@ -85,12 +84,12 @@ static NativeSelectableChannel serverSocket(int port) { System.exit(1); } System.out.println("bind+listen succeeded"); - return NativeSelectableChannel.forServerSocket(fd); + return new NativeServerSocketChannel(fd); } private static abstract class IO { - protected final NativeSelectableChannel channel; + protected final SelectableChannel channel; protected final Selector selector; - public IO(Selector selector, NativeSelectableChannel ch) { + public IO(Selector selector, SelectableChannel ch) { this.selector = selector; this.channel = ch; } @@ -98,15 +97,15 @@ public IO(Selector selector, NativeSelectableChannel ch) { public abstract void write(); } private static class Accepter extends IO { - public Accepter(Selector selector, NativeSelectableChannel ch) { + public Accepter(Selector selector, NativeServerSocketChannel ch) { super(selector, ch); } public void read() { SockAddrIN sin = new SockAddrIN(); int[] addrSize = { StructUtil.getSize(sin) }; - int clientfd = libc.accept(channel.getFD(), sin, addrSize); + int clientfd = libc.accept(((NativeSelectableChannel) channel).getFD(), sin, addrSize); System.out.println("client fd = " + clientfd); - NativeSelectableChannel ch = NativeSelectableChannel.forSocket(clientfd); + NativeSocketChannel ch = new NativeSocketChannel(clientfd); try { ch.configureBlocking(false); ch.register(selector, SelectionKey.OP_READ, new Client(selector, ch)); @@ -120,16 +119,16 @@ public void write() { } private static class Client extends IO { private final ByteBuffer buf = ByteBuffer.allocateDirect(1024); - public Client(Selector selector, NativeSelectableChannel ch) { + public Client(Selector selector, NativeSocketChannel ch) { super(selector, ch); } public void read() { - int n = libc.read(channel.getFD(), buf, buf.remaining()); + int n = libc.read(((NativeSelectableChannel) channel).getFD(), buf, buf.remaining()); System.out.println("Read " + n + " bytes from client"); if (n <= 0) { SelectionKey k = channel.keyFor(selector); k.cancel(); - libc.close(channel.getFD()); + libc.close(((NativeSelectableChannel) channel).getFD()); return; } buf.position(n); @@ -138,7 +137,7 @@ public void read() { } public void write() { while (buf.hasRemaining()) { - int n = libc.write(channel.getFD(), buf, buf.remaining()); + int n = libc.write(((NativeSelectableChannel) channel).getFD(), buf, buf.remaining()); System.out.println("write returned " + n); if (n > 0) { buf.position(buf.position() + n); @@ -148,7 +147,7 @@ public void write() { } if (n < 0) { channel.keyFor(selector).cancel(); - libc.close(channel.getFD()); + libc.close(((NativeSelectableChannel) channel).getFD()); return; } } @@ -162,7 +161,7 @@ public static void main(String[] args) { try { Selector selector = NativeSelectorProvider.getInstance().openSelector(); for (int i = 0; i < 2; ++i) { - NativeSelectableChannel ch = serverSocket(baseport + i); + NativeServerSocketChannel ch = serverSocket(baseport + i); ch.configureBlocking(false); ch.register(selector, SelectionKey.OP_ACCEPT, new Accepter(selector, ch)); }