Resurrect channel deregistration and constructor changes

Motivation:

Due to the complexity of handling deregistration and re-registration of
a channel, we previously decided to remove the deregister() operation
completely to simplify our code.  However, we realized that it shouldn't
be that complicated to implement it during our discussion about making
I/O scheduling more flexible and more customizable [1], and thus the
removal of deregistration and re-registration is unnecessary now.

Modification:

- Revert commit c149f4bcc0
- Revert commit e743a27e75
- Make some additional adjustments

Result:

- deregister(), fireChannelUnregistered(), and channelRegistered() were
  added back..
- Channel constructors do not require an EventLoop anymore.

[1] https://github.com/netty/netty/issues/2250
This commit is contained in:
Norman Maurer 2014-04-22 14:38:10 +02:00 committed by Trustin Lee
parent 797d6d94a4
commit 48f2e705d9
77 changed files with 891 additions and 921 deletions

View File

@ -195,6 +195,14 @@ public class LoggingHandler extends ChannelHandlerAdapter {
ctx.fireChannelRegistered(); ctx.fireChannelRegistered();
} }
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
if (logger.isEnabled(internalLevel)) {
logger.log(internalLevel, format(ctx, "UNREGISTERED"));
}
ctx.fireChannelUnregistered();
}
@Override @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception { public void channelActive(ChannelHandlerContext ctx) throws Exception {
if (logger.isEnabled(internalLevel)) { if (logger.isEnabled(internalLevel)) {

View File

@ -21,7 +21,6 @@ import io.netty.bootstrap.ChannelFactory;
import io.netty.bootstrap.ServerBootstrap; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup; import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.oio.OioEventLoopGroup; import io.netty.channel.oio.OioEventLoopGroup;
@ -109,8 +108,8 @@ public class SocketTestPermutation {
public Bootstrap newInstance() { public Bootstrap newInstance() {
return new Bootstrap().group(nioWorkerGroup).channelFactory(new ChannelFactory<Channel>() { return new Bootstrap().group(nioWorkerGroup).channelFactory(new ChannelFactory<Channel>() {
@Override @Override
public Channel newChannel(EventLoop loop) { public Channel newChannel() {
return new NioDatagramChannel(loop, InternetProtocolFamily.IPv4); return new NioDatagramChannel(InternetProtocolFamily.IPv4);
} }
@Override @Override

View File

@ -32,12 +32,12 @@ abstract class AbstractEpollChannel extends AbstractChannel {
volatile int fd; volatile int fd;
int id; int id;
AbstractEpollChannel(EventLoop eventLoop, int fd, int flag) { AbstractEpollChannel(int fd, int flag) {
this(null, eventLoop, fd, flag, false); this(null, fd, flag, false);
} }
AbstractEpollChannel(Channel parent, EventLoop eventLoop, int fd, int flag, boolean active) { AbstractEpollChannel(Channel parent, int fd, int flag, boolean active) {
super(parent, eventLoop); super(parent);
this.fd = fd; this.fd = fd;
readFlag = flag; readFlag = flag;
flags |= flag; flags |= flag;

View File

@ -23,7 +23,6 @@ import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoop;
import io.netty.channel.RecvByteBufAllocator; import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.DatagramChannelConfig; import io.netty.channel.socket.DatagramChannelConfig;
@ -51,8 +50,8 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements
private volatile boolean connected; private volatile boolean connected;
private final EpollDatagramChannelConfig config; private final EpollDatagramChannelConfig config;
public EpollDatagramChannel(EventLoop loop) { public EpollDatagramChannel() {
super(loop, Native.socketDgramFd(), Native.EPOLLIN); super(Native.socketDgramFd(), Native.EPOLLIN);
config = new EpollDatagramChannelConfig(this); config = new EpollDatagramChannelConfig(this);
} }

View File

@ -19,7 +19,6 @@ import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoop; import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel; import io.netty.channel.socket.ServerSocketChannel;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@ -32,13 +31,11 @@ import java.net.SocketAddress;
public final class EpollServerSocketChannel extends AbstractEpollChannel implements ServerSocketChannel { public final class EpollServerSocketChannel extends AbstractEpollChannel implements ServerSocketChannel {
private final EpollServerSocketChannelConfig config; private final EpollServerSocketChannelConfig config;
private final EventLoopGroup childGroup;
private volatile InetSocketAddress local; private volatile InetSocketAddress local;
public EpollServerSocketChannel(EventLoop eventLoop, EventLoopGroup childGroup) { public EpollServerSocketChannel() {
super(eventLoop, Native.socketStreamFd(), Native.EPOLLACCEPT); super(Native.socketStreamFd(), Native.EPOLLACCEPT);
config = new EpollServerSocketChannelConfig(this); config = new EpollServerSocketChannelConfig(this);
this.childGroup = childGroup;
} }
@Override @Override
@ -81,11 +78,6 @@ public final class EpollServerSocketChannel extends AbstractEpollChannel impleme
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public EventLoopGroup childEventLoopGroup() {
return childGroup;
}
final class EpollServerSocketUnsafe extends AbstractEpollUnsafe { final class EpollServerSocketUnsafe extends AbstractEpollUnsafe {
@Override @Override
@ -109,8 +101,7 @@ public final class EpollServerSocketChannel extends AbstractEpollChannel impleme
} }
try { try {
readPending = false; readPending = false;
pipeline.fireChannelRead(new EpollSocketChannel(EpollServerSocketChannel.this, pipeline.fireChannelRead(new EpollSocketChannel(EpollServerSocketChannel.this, socketFd));
childEventLoopGroup().next(), socketFd));
} catch (Throwable t) { } catch (Throwable t) {
// keep on reading as we use epoll ET and need to consume everything from the socket // keep on reading as we use epoll ET and need to consume everything from the socket
pipeline.fireChannelReadComplete(); pipeline.fireChannelReadComplete();

View File

@ -66,8 +66,8 @@ public final class EpollSocketChannel extends AbstractEpollChannel implements So
private volatile boolean inputShutdown; private volatile boolean inputShutdown;
private volatile boolean outputShutdown; private volatile boolean outputShutdown;
EpollSocketChannel(Channel parent, EventLoop eventLoop, int fd) { EpollSocketChannel(Channel parent, int fd) {
super(parent, eventLoop, fd, Native.EPOLLIN, true); super(parent, fd, Native.EPOLLIN, true);
config = new EpollSocketChannelConfig(this); config = new EpollSocketChannelConfig(this);
// Directly cache the remote and local addresses // Directly cache the remote and local addresses
// See https://github.com/netty/netty/issues/2359 // See https://github.com/netty/netty/issues/2359
@ -75,8 +75,8 @@ public final class EpollSocketChannel extends AbstractEpollChannel implements So
local = Native.localAddress(fd); local = Native.localAddress(fd);
} }
public EpollSocketChannel(EventLoop eventLoop) { public EpollSocketChannel() {
super(eventLoop, Native.socketStreamFd(), Native.EPOLLIN); super(Native.socketStreamFd(), Native.EPOLLIN);
config = new EpollSocketChannelConfig(this); config = new EpollSocketChannelConfig(this);
} }

View File

@ -19,7 +19,6 @@ import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ChannelFactory; import io.netty.bootstrap.ChannelFactory;
import io.netty.bootstrap.ServerBootstrap; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup; import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.InternetProtocolFamily; import io.netty.channel.socket.InternetProtocolFamily;
import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioDatagramChannel;
@ -100,8 +99,8 @@ class EpollSocketTestPermutation extends SocketTestPermutation {
public Bootstrap newInstance() { public Bootstrap newInstance() {
return new Bootstrap().group(nioWorkerGroup).channelFactory(new ChannelFactory<Channel>() { return new Bootstrap().group(nioWorkerGroup).channelFactory(new ChannelFactory<Channel>() {
@Override @Override
public Channel newChannel(EventLoop loop) { public Channel newChannel() {
return new NioDatagramChannel(loop, InternetProtocolFamily.IPv4); return new NioDatagramChannel(InternetProtocolFamily.IPv4);
} }
@Override @Override

View File

@ -19,7 +19,6 @@ import gnu.io.CommPort;
import gnu.io.CommPortIdentifier; import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort; import gnu.io.SerialPort;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoop;
import io.netty.channel.oio.OioByteStreamChannel; import io.netty.channel.oio.OioByteStreamChannel;
import java.net.SocketAddress; import java.net.SocketAddress;
@ -40,8 +39,8 @@ public class RxtxChannel extends OioByteStreamChannel {
private RxtxDeviceAddress deviceAddress; private RxtxDeviceAddress deviceAddress;
private SerialPort serialPort; private SerialPort serialPort;
public RxtxChannel(EventLoop eventLoop) { public RxtxChannel() {
super(null, eventLoop); super(null);
config = new DefaultRxtxChannelConfig(this); config = new DefaultRxtxChannelConfig(this);
} }

View File

@ -27,7 +27,6 @@ import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelMetadata; import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoop;
import io.netty.channel.RecvByteBufAllocator; import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.nio.AbstractNioMessageChannel; import io.netty.channel.nio.AbstractNioMessageChannel;
import io.netty.channel.sctp.DefaultSctpChannelConfig; import io.netty.channel.sctp.DefaultSctpChannelConfig;
@ -82,15 +81,15 @@ public class NioSctpChannel extends AbstractNioMessageChannel implements io.nett
/** /**
* Create a new instance * Create a new instance
*/ */
public NioSctpChannel(EventLoop eventLoop) { public NioSctpChannel() {
this(eventLoop, newSctpChannel()); this(newSctpChannel());
} }
/** /**
* Create a new instance using {@link SctpChannel} * Create a new instance using {@link SctpChannel}
*/ */
public NioSctpChannel(EventLoop eventLoop, SctpChannel sctpChannel) { public NioSctpChannel(SctpChannel sctpChannel) {
this(null, eventLoop, sctpChannel); this(null, sctpChannel);
} }
/** /**
@ -100,8 +99,8 @@ public class NioSctpChannel extends AbstractNioMessageChannel implements io.nett
* or {@code null}. * or {@code null}.
* @param sctpChannel the underlying {@link SctpChannel} * @param sctpChannel the underlying {@link SctpChannel}
*/ */
public NioSctpChannel(Channel parent, EventLoop eventLoop, SctpChannel sctpChannel) { public NioSctpChannel(Channel parent, SctpChannel sctpChannel) {
super(parent, eventLoop, sctpChannel, SelectionKey.OP_READ); super(parent, sctpChannel, SelectionKey.OP_READ);
try { try {
sctpChannel.configureBlocking(false); sctpChannel.configureBlocking(false);
config = new NioSctpChannelConfig(this, sctpChannel); config = new NioSctpChannelConfig(this, sctpChannel);

View File

@ -22,9 +22,7 @@ import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelMetadata; import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoop; import io.netty.channel.nio.AbstractNioMessageChannel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.AbstractNioMessageServerChannel;
import io.netty.channel.sctp.DefaultSctpServerChannelConfig; import io.netty.channel.sctp.DefaultSctpServerChannelConfig;
import io.netty.channel.sctp.SctpServerChannelConfig; import io.netty.channel.sctp.SctpServerChannelConfig;
@ -46,9 +44,8 @@ import java.util.Set;
* Be aware that not all operations systems support SCTP. Please refer to the documentation of your operation system, * Be aware that not all operations systems support SCTP. Please refer to the documentation of your operation system,
* to understand what you need to do to use it. Also this feature is only supported on Java 7+. * to understand what you need to do to use it. Also this feature is only supported on Java 7+.
*/ */
public class NioSctpServerChannel extends AbstractNioMessageServerChannel public class NioSctpServerChannel extends AbstractNioMessageChannel
implements io.netty.channel.sctp.SctpServerChannel { implements io.netty.channel.sctp.SctpServerChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(false); private static final ChannelMetadata METADATA = new ChannelMetadata(false);
private static SctpServerChannel newSocket() { private static SctpServerChannel newSocket() {
@ -65,9 +62,9 @@ public class NioSctpServerChannel extends AbstractNioMessageServerChannel
/** /**
* Create a new instance * Create a new instance
*/ */
public NioSctpServerChannel(EventLoop eventLoop, EventLoopGroup childGroup) { public NioSctpServerChannel() {
super(null, eventLoop, childGroup, newSocket(), SelectionKey.OP_ACCEPT); super(null, newSocket(), SelectionKey.OP_ACCEPT);
config = new NioSctpServerChannelConfig(this, javaChannel()); config = new DefaultSctpServerChannelConfig(this, javaChannel());
} }
@Override @Override
@ -143,7 +140,7 @@ public class NioSctpServerChannel extends AbstractNioMessageServerChannel
if (ch == null) { if (ch == null) {
return 0; return 0;
} }
buf.add(new NioSctpChannel(this, childEventLoopGroup().next(), ch)); buf.add(new NioSctpChannel(this, ch));
return 1; return 1;
} }

View File

@ -26,7 +26,6 @@ import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelMetadata; import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoop;
import io.netty.channel.RecvByteBufAllocator; import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.oio.AbstractOioMessageChannel; import io.netty.channel.oio.AbstractOioMessageChannel;
import io.netty.channel.sctp.DefaultSctpChannelConfig; import io.netty.channel.sctp.DefaultSctpChannelConfig;
@ -88,8 +87,8 @@ public class OioSctpChannel extends AbstractOioMessageChannel
/** /**
* Create a new instance with an new {@link SctpChannel}. * Create a new instance with an new {@link SctpChannel}.
*/ */
public OioSctpChannel(EventLoop eventLoop) { public OioSctpChannel() {
this(eventLoop, openChannel()); this(openChannel());
} }
/** /**
@ -97,8 +96,8 @@ public class OioSctpChannel extends AbstractOioMessageChannel
* *
* @param ch the {@link SctpChannel} which is used by this instance * @param ch the {@link SctpChannel} which is used by this instance
*/ */
public OioSctpChannel(EventLoop eventLoop, SctpChannel ch) { public OioSctpChannel(SctpChannel ch) {
this(null, eventLoop, ch); this(null, ch);
} }
/** /**
@ -108,8 +107,8 @@ public class OioSctpChannel extends AbstractOioMessageChannel
* {@link} has no parent as it was created by your self. * {@link} has no parent as it was created by your self.
* @param ch the {@link SctpChannel} which is used by this instance * @param ch the {@link SctpChannel} which is used by this instance
*/ */
public OioSctpChannel(Channel parent, EventLoop eventLoop, SctpChannel ch) { public OioSctpChannel(Channel parent, SctpChannel ch) {
super(parent, eventLoop); super(parent);
this.ch = ch; this.ch = ch;
boolean success = false; boolean success = false;
try { try {

View File

@ -22,9 +22,7 @@ import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelMetadata; import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoop; import io.netty.channel.oio.AbstractOioMessageChannel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.oio.AbstractOioMessageServerChannel;
import io.netty.channel.sctp.DefaultSctpServerChannelConfig; import io.netty.channel.sctp.DefaultSctpServerChannelConfig;
import io.netty.channel.sctp.SctpServerChannelConfig; import io.netty.channel.sctp.SctpServerChannelConfig;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
@ -49,7 +47,7 @@ import java.util.Set;
* Be aware that not all operations systems support SCTP. Please refer to the documentation of your operation system, * Be aware that not all operations systems support SCTP. Please refer to the documentation of your operation system,
* to understand what you need to do to use it. Also this feature is only supported on Java 7+. * to understand what you need to do to use it. Also this feature is only supported on Java 7+.
*/ */
public class OioSctpServerChannel extends AbstractOioMessageServerChannel public class OioSctpServerChannel extends AbstractOioMessageChannel
implements io.netty.channel.sctp.SctpServerChannel { implements io.netty.channel.sctp.SctpServerChannel {
private static final InternalLogger logger = private static final InternalLogger logger =
@ -72,8 +70,8 @@ public class OioSctpServerChannel extends AbstractOioMessageServerChannel
/** /**
* Create a new instance with an new {@link SctpServerChannel} * Create a new instance with an new {@link SctpServerChannel}
*/ */
public OioSctpServerChannel(EventLoop eventLoop, EventLoopGroup childGroup) { public OioSctpServerChannel() {
this(eventLoop, childGroup, newServerSocket()); this(newServerSocket());
} }
/** /**
@ -81,8 +79,8 @@ public class OioSctpServerChannel extends AbstractOioMessageServerChannel
* *
* @param sch the {@link SctpServerChannel} which is used by this instance * @param sch the {@link SctpServerChannel} which is used by this instance
*/ */
public OioSctpServerChannel(EventLoop eventLoop, EventLoopGroup childGroup, SctpServerChannel sch) { public OioSctpServerChannel(SctpServerChannel sch) {
super(null, eventLoop, childGroup); super(null);
if (sch == null) { if (sch == null) {
throw new NullPointerException("sctp server channel"); throw new NullPointerException("sctp server channel");
} }
@ -198,7 +196,7 @@ public class OioSctpServerChannel extends AbstractOioMessageServerChannel
if (key.isAcceptable()) { if (key.isAcceptable()) {
s = sch.accept(); s = sch.accept();
if (s != null) { if (s != null) {
buf.add(new OioSctpChannel(this, childEventLoopGroup().next(), s)); buf.add(new OioSctpChannel(this, s));
acceptedChannels ++; acceptedChannels ++;
} }
} }

View File

@ -19,9 +19,7 @@ import com.barchart.udt.TypeUDT;
import com.barchart.udt.nio.ServerSocketChannelUDT; import com.barchart.udt.nio.ServerSocketChannelUDT;
import io.netty.channel.ChannelException; import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.EventLoop; import io.netty.channel.nio.AbstractNioMessageChannel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.AbstractNioMessageServerChannel;
import io.netty.channel.udt.DefaultUdtServerChannelConfig; import io.netty.channel.udt.DefaultUdtServerChannelConfig;
import io.netty.channel.udt.UdtServerChannel; import io.netty.channel.udt.UdtServerChannel;
import io.netty.channel.udt.UdtServerChannelConfig; import io.netty.channel.udt.UdtServerChannelConfig;
@ -36,16 +34,15 @@ import static java.nio.channels.SelectionKey.*;
/** /**
* Common base for Netty Byte/Message UDT Stream/Datagram acceptors. * Common base for Netty Byte/Message UDT Stream/Datagram acceptors.
*/ */
public abstract class NioUdtAcceptorChannel extends AbstractNioMessageServerChannel implements UdtServerChannel { public abstract class NioUdtAcceptorChannel extends AbstractNioMessageChannel implements UdtServerChannel {
protected static final InternalLogger logger = protected static final InternalLogger logger =
InternalLoggerFactory.getInstance(NioUdtAcceptorChannel.class); InternalLoggerFactory.getInstance(NioUdtAcceptorChannel.class);
private final UdtServerChannelConfig config; private final UdtServerChannelConfig config;
protected NioUdtAcceptorChannel(EventLoop eventLoop, EventLoopGroup childGroup, protected NioUdtAcceptorChannel(final ServerSocketChannelUDT channelUDT) {
ServerSocketChannelUDT channelUDT) { super(null, channelUDT, OP_ACCEPT);
super(null, eventLoop, childGroup, channelUDT, OP_ACCEPT);
try { try {
channelUDT.configureBlocking(false); channelUDT.configureBlocking(false);
config = new DefaultUdtServerChannelConfig(this, channelUDT, true); config = new DefaultUdtServerChannelConfig(this, channelUDT, true);
@ -61,8 +58,8 @@ public abstract class NioUdtAcceptorChannel extends AbstractNioMessageServerChan
} }
} }
protected NioUdtAcceptorChannel(EventLoop eventLoop, EventLoopGroup childGroup, final TypeUDT type) { protected NioUdtAcceptorChannel(final TypeUDT type) {
this(eventLoop, childGroup, NioUdtProvider.newAcceptorChannelUDT(type)); this(NioUdtProvider.newAcceptorChannelUDT(type));
} }
@Override @Override

View File

@ -18,8 +18,6 @@ package io.netty.channel.udt.nio;
import com.barchart.udt.TypeUDT; import com.barchart.udt.TypeUDT;
import com.barchart.udt.nio.SocketChannelUDT; import com.barchart.udt.nio.SocketChannelUDT;
import io.netty.channel.ChannelMetadata; import io.netty.channel.ChannelMetadata;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import java.util.List; import java.util.List;
@ -30,8 +28,8 @@ public class NioUdtByteAcceptorChannel extends NioUdtAcceptorChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(false); private static final ChannelMetadata METADATA = new ChannelMetadata(false);
public NioUdtByteAcceptorChannel(EventLoop eventLoop, EventLoopGroup childGroup) { public NioUdtByteAcceptorChannel() {
super(eventLoop, childGroup, TypeUDT.STREAM); super(TypeUDT.STREAM);
} }
@Override @Override
@ -40,7 +38,7 @@ public class NioUdtByteAcceptorChannel extends NioUdtAcceptorChannel {
if (channelUDT == null) { if (channelUDT == null) {
return 0; return 0;
} else { } else {
buf.add(new NioUdtByteConnectorChannel(this, childEventLoopGroup().next(), channelUDT)); buf.add(new NioUdtByteConnectorChannel(this, channelUDT));
return 1; return 1;
} }
} }

View File

@ -21,7 +21,6 @@ import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelException; import io.netty.channel.ChannelException;
import io.netty.channel.ChannelMetadata; import io.netty.channel.ChannelMetadata;
import io.netty.channel.EventLoop;
import io.netty.channel.FileRegion; import io.netty.channel.FileRegion;
import io.netty.channel.nio.AbstractNioByteChannel; import io.netty.channel.nio.AbstractNioByteChannel;
import io.netty.channel.udt.DefaultUdtChannelConfig; import io.netty.channel.udt.DefaultUdtChannelConfig;
@ -47,12 +46,12 @@ public class NioUdtByteConnectorChannel extends AbstractNioByteChannel implement
private final UdtChannelConfig config; private final UdtChannelConfig config;
public NioUdtByteConnectorChannel(EventLoop eventLoop) { public NioUdtByteConnectorChannel() {
this(eventLoop, TypeUDT.STREAM); this(TypeUDT.STREAM);
} }
public NioUdtByteConnectorChannel(Channel parent, EventLoop eventLoop, SocketChannelUDT channelUDT) { public NioUdtByteConnectorChannel(final Channel parent, final SocketChannelUDT channelUDT) {
super(parent, eventLoop, channelUDT); super(parent, channelUDT);
try { try {
channelUDT.configureBlocking(false); channelUDT.configureBlocking(false);
switch (channelUDT.socketUDT().status()) { switch (channelUDT.socketUDT().status()) {
@ -76,12 +75,12 @@ public class NioUdtByteConnectorChannel extends AbstractNioByteChannel implement
} }
} }
public NioUdtByteConnectorChannel(EventLoop eventLoop, final SocketChannelUDT channelUDT) { public NioUdtByteConnectorChannel(final SocketChannelUDT channelUDT) {
this(null, eventLoop, channelUDT); this(null, channelUDT);
} }
public NioUdtByteConnectorChannel(EventLoop eventLoop, final TypeUDT type) { public NioUdtByteConnectorChannel(final TypeUDT type) {
this(eventLoop, NioUdtProvider.newConnectorChannelUDT(type)); this(NioUdtProvider.newConnectorChannelUDT(type));
} }
@Override @Override

View File

@ -15,17 +15,15 @@
*/ */
package io.netty.channel.udt.nio; package io.netty.channel.udt.nio;
import com.barchart.udt.TypeUDT; import com.barchart.udt.TypeUDT;
import io.netty.channel.EventLoop;
/** /**
* Byte Channel Rendezvous for UDT Streams. * Byte Channel Rendezvous for UDT Streams.
*/ */
public class NioUdtByteRendezvousChannel extends NioUdtByteConnectorChannel { public class NioUdtByteRendezvousChannel extends NioUdtByteConnectorChannel {
public NioUdtByteRendezvousChannel(EventLoop eventLoop) { public NioUdtByteRendezvousChannel() {
super(eventLoop, NioUdtProvider.newRendezvousChannelUDT(TypeUDT.STREAM)); super(NioUdtProvider.newRendezvousChannelUDT(TypeUDT.STREAM));
} }
} }

View File

@ -18,8 +18,6 @@ package io.netty.channel.udt.nio;
import com.barchart.udt.TypeUDT; import com.barchart.udt.TypeUDT;
import com.barchart.udt.nio.SocketChannelUDT; import com.barchart.udt.nio.SocketChannelUDT;
import io.netty.channel.ChannelMetadata; import io.netty.channel.ChannelMetadata;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import java.util.List; import java.util.List;
@ -30,8 +28,8 @@ public class NioUdtMessageAcceptorChannel extends NioUdtAcceptorChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(false); private static final ChannelMetadata METADATA = new ChannelMetadata(false);
public NioUdtMessageAcceptorChannel(EventLoop eventLoop, EventLoopGroup childGroup) { public NioUdtMessageAcceptorChannel() {
super(eventLoop, childGroup, TypeUDT.DATAGRAM); super(TypeUDT.DATAGRAM);
} }
@Override @Override
@ -40,7 +38,7 @@ public class NioUdtMessageAcceptorChannel extends NioUdtAcceptorChannel {
if (channelUDT == null) { if (channelUDT == null) {
return 0; return 0;
} else { } else {
buf.add(new NioUdtMessageConnectorChannel(this, childEventLoopGroup().next(), channelUDT)); buf.add(new NioUdtMessageConnectorChannel(this, channelUDT));
return 1; return 1;
} }
} }

View File

@ -22,7 +22,6 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelException; import io.netty.channel.ChannelException;
import io.netty.channel.ChannelMetadata; import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.EventLoop;
import io.netty.channel.nio.AbstractNioMessageChannel; import io.netty.channel.nio.AbstractNioMessageChannel;
import io.netty.channel.udt.DefaultUdtChannelConfig; import io.netty.channel.udt.DefaultUdtChannelConfig;
import io.netty.channel.udt.UdtChannel; import io.netty.channel.udt.UdtChannel;
@ -51,12 +50,12 @@ public class NioUdtMessageConnectorChannel extends AbstractNioMessageChannel imp
private final UdtChannelConfig config; private final UdtChannelConfig config;
public NioUdtMessageConnectorChannel(EventLoop eventLoop) { public NioUdtMessageConnectorChannel() {
this(eventLoop, TypeUDT.DATAGRAM); this(TypeUDT.DATAGRAM);
} }
public NioUdtMessageConnectorChannel(final Channel parent, EventLoop eventLoop, final SocketChannelUDT channelUDT) { public NioUdtMessageConnectorChannel(final Channel parent, final SocketChannelUDT channelUDT) {
super(parent, eventLoop, channelUDT, OP_READ); super(parent, channelUDT, OP_READ);
try { try {
channelUDT.configureBlocking(false); channelUDT.configureBlocking(false);
switch (channelUDT.socketUDT().status()) { switch (channelUDT.socketUDT().status()) {
@ -80,12 +79,12 @@ public class NioUdtMessageConnectorChannel extends AbstractNioMessageChannel imp
} }
} }
public NioUdtMessageConnectorChannel(EventLoop eventLoop, final SocketChannelUDT channelUDT) { public NioUdtMessageConnectorChannel(final SocketChannelUDT channelUDT) {
this(null, eventLoop, channelUDT); this(null, channelUDT);
} }
public NioUdtMessageConnectorChannel(EventLoop eventLoop, final TypeUDT type) { public NioUdtMessageConnectorChannel(final TypeUDT type) {
this(eventLoop, NioUdtProvider.newConnectorChannelUDT(type)); this(NioUdtProvider.newConnectorChannelUDT(type));
} }
@Override @Override

View File

@ -16,7 +16,6 @@
package io.netty.channel.udt.nio; package io.netty.channel.udt.nio;
import com.barchart.udt.TypeUDT; import com.barchart.udt.TypeUDT;
import io.netty.channel.EventLoop;
import io.netty.channel.udt.UdtMessage; import io.netty.channel.udt.UdtMessage;
/** /**
@ -24,9 +23,10 @@ import io.netty.channel.udt.UdtMessage;
* <p> * <p>
* Note: send/receive must use {@link UdtMessage} in the pipeline * Note: send/receive must use {@link UdtMessage} in the pipeline
*/ */
public class NioUdtMessageRendezvousChannel extends NioUdtMessageConnectorChannel { public class NioUdtMessageRendezvousChannel extends
NioUdtMessageConnectorChannel {
public NioUdtMessageRendezvousChannel(EventLoop eventLoop) { public NioUdtMessageRendezvousChannel() {
super(eventLoop, NioUdtProvider.newRendezvousChannelUDT(TypeUDT.DATAGRAM)); super(NioUdtProvider.newRendezvousChannelUDT(TypeUDT.DATAGRAM));
} }
} }

View File

@ -24,13 +24,10 @@ import com.barchart.udt.nio.SelectorProviderUDT;
import com.barchart.udt.nio.ServerSocketChannelUDT; import com.barchart.udt.nio.ServerSocketChannelUDT;
import com.barchart.udt.nio.SocketChannelUDT; import com.barchart.udt.nio.SocketChannelUDT;
import io.netty.bootstrap.ChannelFactory; import io.netty.bootstrap.ChannelFactory;
import io.netty.bootstrap.ServerChannelFactory;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelException; import io.netty.channel.ChannelException;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.udt.UdtChannel;
import io.netty.channel.udt.UdtServerChannel; import io.netty.channel.udt.UdtServerChannel;
import io.netty.channel.udt.UdtChannel;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.spi.SelectorProvider; import java.nio.channels.spi.SelectorProvider;
@ -42,21 +39,21 @@ import java.nio.channels.spi.SelectorProvider;
* <p> * <p>
* Provides {@link SelectorProvider} for UDT channels. * Provides {@link SelectorProvider} for UDT channels.
*/ */
public abstract class NioUdtProvider { public final class NioUdtProvider<T extends UdtChannel> implements ChannelFactory<T> {
/** /**
* {@link ChannelFactory} for UDT Byte Acceptor. See {@link TypeUDT#STREAM} * {@link ChannelFactory} for UDT Byte Acceptor. See {@link TypeUDT#STREAM}
* and {@link KindUDT#ACCEPTOR}. * and {@link KindUDT#ACCEPTOR}.
*/ */
public static final ServerChannelFactory<UdtServerChannel> BYTE_ACCEPTOR = public static final ChannelFactory<UdtServerChannel> BYTE_ACCEPTOR = new NioUdtProvider<UdtServerChannel>(
new NioUdtServerChannelFactory<UdtServerChannel>(TypeUDT.STREAM, KindUDT.ACCEPTOR); TypeUDT.STREAM, KindUDT.ACCEPTOR);
/** /**
* {@link ChannelFactory} for UDT Byte Connector. See {@link TypeUDT#STREAM} * {@link ChannelFactory} for UDT Byte Connector. See {@link TypeUDT#STREAM}
* and {@link KindUDT#CONNECTOR}. * and {@link KindUDT#CONNECTOR}.
*/ */
public static final ChannelFactory<UdtChannel> BYTE_CONNECTOR = public static final ChannelFactory<UdtChannel> BYTE_CONNECTOR = new NioUdtProvider<UdtChannel>(
new NioUdtChannelFactory<UdtChannel>(TypeUDT.STREAM, KindUDT.CONNECTOR); TypeUDT.STREAM, KindUDT.CONNECTOR);
/** /**
* {@link SelectorProvider} for UDT Byte channels. See * {@link SelectorProvider} for UDT Byte channels. See
@ -68,22 +65,22 @@ public abstract class NioUdtProvider {
* {@link ChannelFactory} for UDT Byte Rendezvous. See * {@link ChannelFactory} for UDT Byte Rendezvous. See
* {@link TypeUDT#STREAM} and {@link KindUDT#RENDEZVOUS}. * {@link TypeUDT#STREAM} and {@link KindUDT#RENDEZVOUS}.
*/ */
public static final ChannelFactory<UdtChannel> BYTE_RENDEZVOUS = public static final ChannelFactory<UdtChannel> BYTE_RENDEZVOUS = new NioUdtProvider<UdtChannel>(
new NioUdtChannelFactory<UdtChannel>(TypeUDT.STREAM, KindUDT.RENDEZVOUS); TypeUDT.STREAM, KindUDT.RENDEZVOUS);
/** /**
* {@link ChannelFactory} for UDT Message Acceptor. See * {@link ChannelFactory} for UDT Message Acceptor. See
* {@link TypeUDT#DATAGRAM} and {@link KindUDT#ACCEPTOR}. * {@link TypeUDT#DATAGRAM} and {@link KindUDT#ACCEPTOR}.
*/ */
public static final ServerChannelFactory<UdtServerChannel> MESSAGE_ACCEPTOR = public static final ChannelFactory<UdtServerChannel> MESSAGE_ACCEPTOR = new NioUdtProvider<UdtServerChannel>(
new NioUdtServerChannelFactory<UdtServerChannel>(TypeUDT.DATAGRAM, KindUDT.ACCEPTOR); TypeUDT.DATAGRAM, KindUDT.ACCEPTOR);
/** /**
* {@link ChannelFactory} for UDT Message Connector. See * {@link ChannelFactory} for UDT Message Connector. See
* {@link TypeUDT#DATAGRAM} and {@link KindUDT#CONNECTOR}. * {@link TypeUDT#DATAGRAM} and {@link KindUDT#CONNECTOR}.
*/ */
public static final ChannelFactory<UdtChannel> MESSAGE_CONNECTOR = public static final ChannelFactory<UdtChannel> MESSAGE_CONNECTOR = new NioUdtProvider<UdtChannel>(
new NioUdtChannelFactory<UdtChannel>(TypeUDT.DATAGRAM, KindUDT.CONNECTOR); TypeUDT.DATAGRAM, KindUDT.CONNECTOR);
/** /**
* {@link SelectorProvider} for UDT Message channels. See * {@link SelectorProvider} for UDT Message channels. See
@ -95,8 +92,8 @@ public abstract class NioUdtProvider {
* {@link ChannelFactory} for UDT Message Rendezvous. See * {@link ChannelFactory} for UDT Message Rendezvous. See
* {@link TypeUDT#DATAGRAM} and {@link KindUDT#RENDEZVOUS}. * {@link TypeUDT#DATAGRAM} and {@link KindUDT#RENDEZVOUS}.
*/ */
public static final ChannelFactory<UdtChannel> MESSAGE_RENDEZVOUS = public static final ChannelFactory<UdtChannel> MESSAGE_RENDEZVOUS = new NioUdtProvider<UdtChannel>(
new NioUdtChannelFactory<UdtChannel>(TypeUDT.DATAGRAM, KindUDT.RENDEZVOUS); TypeUDT.DATAGRAM, KindUDT.RENDEZVOUS);
/** /**
* Expose underlying {@link ChannelUDT} for debugging and monitoring. * Expose underlying {@link ChannelUDT} for debugging and monitoring.
@ -131,7 +128,8 @@ public abstract class NioUdtProvider {
/** /**
* Convenience factory for {@link KindUDT#ACCEPTOR} channels. * Convenience factory for {@link KindUDT#ACCEPTOR} channels.
*/ */
protected static ServerSocketChannelUDT newAcceptorChannelUDT(final TypeUDT type) { protected static ServerSocketChannelUDT newAcceptorChannelUDT(
final TypeUDT type) {
try { try {
return SelectorProviderUDT.from(type).openServerSocketChannel(); return SelectorProviderUDT.from(type).openServerSocketChannel();
} catch (final IOException e) { } catch (final IOException e) {
@ -153,7 +151,8 @@ public abstract class NioUdtProvider {
/** /**
* Convenience factory for {@link KindUDT#RENDEZVOUS} channels. * Convenience factory for {@link KindUDT#RENDEZVOUS} channels.
*/ */
protected static RendezvousChannelUDT newRendezvousChannelUDT(final TypeUDT type) { protected static RendezvousChannelUDT newRendezvousChannelUDT(
final TypeUDT type) {
try { try {
return SelectorProviderUDT.from(type).openRendezvousChannel(); return SelectorProviderUDT.from(type).openRendezvousChannel();
} catch (final IOException e) { } catch (final IOException e) {
@ -195,70 +194,42 @@ public abstract class NioUdtProvider {
} }
/** /**
* Produce new {@link UdtChannel} based on factory {@link #kind()} and {@link #type()} * Produce new {@link UdtChannel} based on factory {@link #kind()} and
* {@link #type()}
*/ */
private static final class NioUdtChannelFactory<T extends UdtChannel>
extends NioUdtProvider implements ChannelFactory<T> {
private NioUdtChannelFactory(final TypeUDT type, final KindUDT kind) {
super(type, kind);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public T newChannel(EventLoop eventLoop) { public T newChannel() {
switch (kind()) { switch (kind) {
case ACCEPTOR: case ACCEPTOR:
throw new IllegalStateException("wrong kind: " + kind()); switch (type) {
case CONNECTOR:
switch (type()) {
case DATAGRAM: case DATAGRAM:
return (T) new NioUdtMessageConnectorChannel(eventLoop); return (T) new NioUdtMessageAcceptorChannel();
case STREAM: case STREAM:
return (T) new NioUdtByteConnectorChannel(eventLoop); return (T) new NioUdtByteAcceptorChannel();
default: default:
throw new IllegalStateException("wrong type: " + type()); throw new IllegalStateException("wrong type=" + type);
}
case RENDEZVOUS:
switch (type()) {
case DATAGRAM:
return (T) new NioUdtMessageRendezvousChannel(eventLoop);
case STREAM:
return (T) new NioUdtByteRendezvousChannel(eventLoop);
default:
throw new IllegalStateException("wrong type: " + type());
}
default:
throw new IllegalStateException("wrong kind: " + kind());
}
}
}
private static final class NioUdtServerChannelFactory<T extends UdtServerChannel> extends NioUdtProvider
implements ServerChannelFactory<T> {
private NioUdtServerChannelFactory(final TypeUDT type, final KindUDT kind) {
super(type, kind);
}
@Override
@SuppressWarnings("unchecked")
public T newChannel(EventLoop eventLoop, EventLoopGroup childGroup) {
switch (kind()) {
case ACCEPTOR:
switch (type()) {
case DATAGRAM:
return (T) new NioUdtMessageAcceptorChannel(eventLoop, childGroup);
case STREAM:
return (T) new NioUdtByteAcceptorChannel(eventLoop, childGroup);
default:
throw new IllegalStateException("wrong type: " + type());
} }
case CONNECTOR: case CONNECTOR:
case RENDEZVOUS: switch (type) {
case DATAGRAM:
return (T) new NioUdtMessageConnectorChannel();
case STREAM:
return (T) new NioUdtByteConnectorChannel();
default: default:
throw new IllegalStateException("wrong kind: " + kind()); throw new IllegalStateException("wrong type=" + type);
} }
case RENDEZVOUS:
switch (type) {
case DATAGRAM:
return (T) new NioUdtMessageRendezvousChannel();
case STREAM:
return (T) new NioUdtByteRendezvousChannel();
default:
throw new IllegalStateException("wrong type=" + type);
}
default:
throw new IllegalStateException("wrong kind=" + kind);
} }
} }

View File

@ -16,8 +16,6 @@
package io.netty.test.udt.nio; package io.netty.test.udt.nio;
import io.netty.channel.EventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.udt.nio.NioUdtByteAcceptorChannel; import io.netty.channel.udt.nio.NioUdtByteAcceptorChannel;
import org.junit.Test; import org.junit.Test;
@ -30,7 +28,6 @@ public class NioUdtByteAcceptorChannelTest extends AbstractUdtTest {
*/ */
@Test @Test
public void metadata() throws Exception { public void metadata() throws Exception {
EventLoop loop = new NioEventLoopGroup().next(); assertEquals(false, new NioUdtByteAcceptorChannel().metadata().hasDisconnect());
assertFalse(new NioUdtByteAcceptorChannel(loop, new NioEventLoopGroup()).metadata().hasDisconnect());
} }
} }

View File

@ -16,8 +16,6 @@
package io.netty.test.udt.nio; package io.netty.test.udt.nio;
import io.netty.channel.EventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.udt.nio.NioUdtByteConnectorChannel; import io.netty.channel.udt.nio.NioUdtByteConnectorChannel;
import org.junit.Test; import org.junit.Test;
@ -30,7 +28,6 @@ public class NioUdtByteConnectorChannelTest extends AbstractUdtTest {
*/ */
@Test @Test
public void metadata() throws Exception { public void metadata() throws Exception {
EventLoop loop = new NioEventLoopGroup().next(); assertEquals(false, new NioUdtByteConnectorChannel().metadata().hasDisconnect());
assertFalse(new NioUdtByteConnectorChannel(loop).metadata().hasDisconnect());
} }
} }

View File

@ -20,7 +20,6 @@ import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Meter; import com.yammer.metrics.core.Meter;
import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoop;
import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.udt.nio.NioUdtByteRendezvousChannel; import io.netty.channel.udt.nio.NioUdtByteRendezvousChannel;
import io.netty.channel.udt.nio.NioUdtProvider; import io.netty.channel.udt.nio.NioUdtProvider;
@ -45,8 +44,7 @@ public class NioUdtByteRendezvousChannelTest extends AbstractUdtTest {
*/ */
@Test @Test
public void metadata() throws Exception { public void metadata() throws Exception {
EventLoop loop = new NioEventLoopGroup().next(); assertFalse(new NioUdtByteRendezvousChannel().metadata().hasDisconnect());
assertFalse(new NioUdtByteRendezvousChannel(loop).metadata().hasDisconnect());
} }
/** /**

View File

@ -16,8 +16,6 @@
package io.netty.test.udt.nio; package io.netty.test.udt.nio;
import io.netty.channel.EventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.udt.nio.NioUdtMessageAcceptorChannel; import io.netty.channel.udt.nio.NioUdtMessageAcceptorChannel;
import org.junit.Test; import org.junit.Test;
@ -30,7 +28,6 @@ public class NioUdtMessageAcceptorChannelTest extends AbstractUdtTest {
*/ */
@Test @Test
public void metadata() throws Exception { public void metadata() throws Exception {
EventLoop loop = new NioEventLoopGroup().next(); assertEquals(false, new NioUdtMessageAcceptorChannel().metadata().hasDisconnect());
assertFalse(new NioUdtMessageAcceptorChannel(loop, new NioEventLoopGroup()).metadata().hasDisconnect());
} }
} }

View File

@ -16,8 +16,6 @@
package io.netty.test.udt.nio; package io.netty.test.udt.nio;
import io.netty.channel.EventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.udt.nio.NioUdtMessageConnectorChannel; import io.netty.channel.udt.nio.NioUdtMessageConnectorChannel;
import org.junit.Test; import org.junit.Test;
@ -30,7 +28,6 @@ public class NioUdtMessageConnectorChannelTest extends AbstractUdtTest {
*/ */
@Test @Test
public void metadata() throws Exception { public void metadata() throws Exception {
EventLoop loop = new NioEventLoopGroup().next(); assertEquals(false, new NioUdtMessageConnectorChannel().metadata().hasDisconnect());
assertFalse(new NioUdtMessageConnectorChannel(loop).metadata().hasDisconnect());
} }
} }

View File

@ -20,7 +20,6 @@ import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Meter; import com.yammer.metrics.core.Meter;
import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoop;
import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.udt.nio.NioUdtMessageRendezvousChannel; import io.netty.channel.udt.nio.NioUdtMessageRendezvousChannel;
import io.netty.channel.udt.nio.NioUdtProvider; import io.netty.channel.udt.nio.NioUdtProvider;
@ -45,8 +44,7 @@ public class NioUdtMessageRendezvousChannelTest extends AbstractUdtTest {
*/ */
@Test @Test
public void metadata() throws Exception { public void metadata() throws Exception {
EventLoop loop = new NioEventLoopGroup().next(); assertFalse(new NioUdtMessageRendezvousChannel().metadata().hasDisconnect());
assertFalse(new NioUdtMessageRendezvousChannel(loop).metadata().hasDisconnect());
} }
/** /**

View File

@ -16,9 +16,6 @@
package io.netty.test.udt.nio; package io.netty.test.udt.nio;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.udt.UdtServerChannel; import io.netty.channel.udt.UdtServerChannel;
import io.netty.channel.udt.nio.NioUdtProvider; import io.netty.channel.udt.nio.NioUdtProvider;
import org.junit.Test; import org.junit.Test;
@ -32,22 +29,18 @@ public class NioUdtProviderTest extends AbstractUdtTest {
*/ */
@Test @Test
public void provideFactory() { public void provideFactory() {
EventLoop loop = new NioEventLoopGroup().next();
EventLoopGroup childGroup = new NioEventLoopGroup();
// bytes // bytes
assertNotNull(NioUdtProvider.BYTE_ACCEPTOR.newChannel(loop, childGroup)); assertNotNull(NioUdtProvider.BYTE_ACCEPTOR.newChannel());
assertNotNull(NioUdtProvider.BYTE_CONNECTOR.newChannel(loop)); assertNotNull(NioUdtProvider.BYTE_CONNECTOR.newChannel());
assertNotNull(NioUdtProvider.BYTE_RENDEZVOUS.newChannel(loop)); assertNotNull(NioUdtProvider.BYTE_RENDEZVOUS.newChannel());
// message // message
assertNotNull(NioUdtProvider.MESSAGE_ACCEPTOR.newChannel(loop, childGroup)); assertNotNull(NioUdtProvider.MESSAGE_ACCEPTOR.newChannel());
assertNotNull(NioUdtProvider.MESSAGE_CONNECTOR.newChannel(loop)); assertNotNull(NioUdtProvider.MESSAGE_CONNECTOR.newChannel());
assertNotNull(NioUdtProvider.MESSAGE_RENDEZVOUS.newChannel(loop)); assertNotNull(NioUdtProvider.MESSAGE_RENDEZVOUS.newChannel());
// acceptor types // acceptor types
assertTrue(NioUdtProvider.BYTE_ACCEPTOR.newChannel(loop, childGroup) instanceof UdtServerChannel); assertTrue(NioUdtProvider.BYTE_ACCEPTOR.newChannel() instanceof UdtServerChannel);
assertTrue(NioUdtProvider.MESSAGE_ACCEPTOR.newChannel(loop, childGroup) instanceof UdtServerChannel); assertTrue(NioUdtProvider.MESSAGE_ACCEPTOR.newChannel() instanceof UdtServerChannel);
} }
} }

View File

@ -17,6 +17,7 @@
package io.netty.bootstrap; package io.netty.bootstrap;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler;
@ -24,7 +25,6 @@ import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.channel.DefaultChannelPromise; import io.netty.channel.DefaultChannelPromise;
import io.netty.channel.EventLoopGroup; import io.netty.channel.EventLoopGroup;
import io.netty.channel.VoidChannel;
import io.netty.util.AttributeKey; import io.netty.util.AttributeKey;
import io.netty.util.concurrent.EventExecutorGroup; import io.netty.util.concurrent.EventExecutorGroup;
import io.netty.util.concurrent.GlobalEventExecutor; import io.netty.util.concurrent.GlobalEventExecutor;
@ -46,6 +46,7 @@ import java.util.Map;
public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable { public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
private volatile EventLoopGroup group; private volatile EventLoopGroup group;
private volatile ChannelFactory<? extends C> channelFactory;
private volatile SocketAddress localAddress; private volatile SocketAddress localAddress;
private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>(); private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>();
private final Map<AttributeKey<?>, Object> attrs = new LinkedHashMap<AttributeKey<?>, Object>(); private final Map<AttributeKey<?>, Object> attrs = new LinkedHashMap<AttributeKey<?>, Object>();
@ -57,6 +58,7 @@ public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C ext
AbstractBootstrap(AbstractBootstrap<B, C> bootstrap) { AbstractBootstrap(AbstractBootstrap<B, C> bootstrap) {
group = bootstrap.group; group = bootstrap.group;
channelFactory = bootstrap.channelFactory;
handler = bootstrap.handler; handler = bootstrap.handler;
localAddress = bootstrap.localAddress; localAddress = bootstrap.localAddress;
synchronized (bootstrap.options) { synchronized (bootstrap.options) {
@ -68,7 +70,8 @@ public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C ext
} }
/** /**
* The {@link EventLoopGroup} which is used to handle all the events for the to-be-created {@link Channel} * The {@link EventLoopGroup} which is used to handle all the events for the to-be-creates
* {@link Channel}
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public B group(EventLoopGroup group) { public B group(EventLoopGroup group) {
@ -82,6 +85,38 @@ public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C ext
return (B) this; return (B) this;
} }
/**
* The {@link Class} which is used to create {@link Channel} instances from.
* You either use this or {@link #channelFactory(ChannelFactory)} if your
* {@link Channel} implementation has no no-args constructor.
*/
public B channel(Class<? extends C> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
}
return channelFactory(new BootstrapChannelFactory<C>(channelClass));
}
/**
* {@link ChannelFactory} which is used to create {@link Channel} instances from
* when calling {@link #bind()}. This method is usually only used if {@link #channel(Class)}
* is not working for you because of some more complex needs. If your {@link Channel} implementation
* has a no-args constructor, its highly recommend to just use {@link #channel(Class)} for
* simplify your code.
*/
@SuppressWarnings("unchecked")
public B channelFactory(ChannelFactory<? extends C> channelFactory) {
if (channelFactory == null) {
throw new NullPointerException("channelFactory");
}
if (this.channelFactory != null) {
throw new IllegalStateException("channelFactory set already");
}
this.channelFactory = channelFactory;
return (B) this;
}
/** /**
* The {@link SocketAddress} which is used to bind the local "end" to. * The {@link SocketAddress} which is used to bind the local "end" to.
* *
@ -166,6 +201,9 @@ public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C ext
if (group == null) { if (group == null) {
throw new IllegalStateException("group not set"); throw new IllegalStateException("group not set");
} }
if (channelFactory == null) {
throw new IllegalStateException("factory not set");
}
return (B) this; return (B) this;
} }
@ -255,16 +293,8 @@ public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C ext
return promise; return promise;
} }
abstract Channel createChannel();
final ChannelFuture initAndRegister() { final ChannelFuture initAndRegister() {
Channel channel; final Channel channel = channelFactory().newChannel();
try {
channel = createChannel();
} catch (Throwable t) {
return VoidChannel.INSTANCE.newFailedFuture(t);
}
try { try {
init(channel); init(channel);
} catch (Throwable t) { } catch (Throwable t) {
@ -272,8 +302,7 @@ public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C ext
return channel.newFailedFuture(t); return channel.newFailedFuture(t);
} }
ChannelPromise regFuture = channel.newPromise(); ChannelFuture regFuture = group().register(channel);
channel.unsafe().register(regFuture);
if (regFuture.cause() != null) { if (regFuture.cause() != null) {
if (channel.isRegistered()) { if (channel.isRegistered()) {
channel.close(); channel.close();
@ -330,6 +359,10 @@ public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C ext
return localAddress; return localAddress;
} }
final ChannelFactory<? extends C> channelFactory() {
return channelFactory;
}
final ChannelHandler handler() { final ChannelHandler handler() {
return handler; return handler;
} }
@ -359,6 +392,11 @@ public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C ext
buf.append(StringUtil.simpleClassName(group)); buf.append(StringUtil.simpleClassName(group));
buf.append(", "); buf.append(", ");
} }
if (channelFactory != null) {
buf.append("channelFactory: ");
buf.append(channelFactory);
buf.append(", ");
}
if (localAddress != null) { if (localAddress != null) {
buf.append("localAddress: "); buf.append("localAddress: ");
buf.append(localAddress); buf.append(localAddress);
@ -391,4 +429,26 @@ public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C ext
} }
return buf.toString(); return buf.toString();
} }
private static final class BootstrapChannelFactory<T extends Channel> implements ChannelFactory<T> {
private final Class<? extends T> clazz;
BootstrapChannelFactory(Class<? extends T> clazz) {
this.clazz = clazz;
}
@Override
public T newChannel() {
try {
return clazz.newInstance();
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}
@Override
public String toString() {
return clazz.getSimpleName() + ".class";
}
}
} }

View File

@ -16,20 +16,15 @@
package io.netty.bootstrap; package io.netty.bootstrap;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoop;
import io.netty.channel.ServerChannel;
import io.netty.util.AttributeKey; import io.netty.util.AttributeKey;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
import java.lang.reflect.Constructor;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
@ -47,58 +42,15 @@ public final class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(Bootstrap.class); private static final InternalLogger logger = InternalLoggerFactory.getInstance(Bootstrap.class);
private volatile ChannelFactory<? extends Channel> channelFactory;
private volatile SocketAddress remoteAddress; private volatile SocketAddress remoteAddress;
public Bootstrap() { } public Bootstrap() { }
private Bootstrap(Bootstrap bootstrap) { private Bootstrap(Bootstrap bootstrap) {
super(bootstrap); super(bootstrap);
channelFactory = bootstrap.channelFactory;
remoteAddress = bootstrap.remoteAddress; remoteAddress = bootstrap.remoteAddress;
} }
/**
* The {@link Class} which is used to create {@link Channel} instances from.
* You either use this or {@link #channelFactory(ChannelFactory)} if your
* {@link Channel} implementation has no no-args constructor.
*/
public Bootstrap channel(Class<? extends Channel> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
}
return channelFactory(new BootstrapChannelFactory<Channel>(channelClass));
}
/**
* {@link ServerChannelFactory} which is used to create {@link ServerChannel} instances when calling
* {@link #bind()}. This method is usually only used if {@link #channel(Class)} is not working for you because of
* some more complex needs. If your {@link Channel} implementation has a no-args constructor, its highly recommend
* to just use {@link #channel(Class)} for simplify your code.
*/
public Bootstrap channelFactory(ChannelFactory<? extends Channel> channelFactory) {
if (channelFactory == null) {
throw new NullPointerException("channelFactory");
}
if (this.channelFactory != null) {
throw new IllegalStateException("channelFactory set already");
}
this.channelFactory = channelFactory;
return this;
}
ChannelFactory<? extends Channel> channelFactory() {
return channelFactory;
}
@Override
Channel createChannel() {
EventLoop eventLoop = group().next();
return channelFactory().newChannel(eventLoop);
}
/** /**
* The {@link SocketAddress} to connect to once the {@link #connect()} method * The {@link SocketAddress} to connect to once the {@link #connect()} method
* is called. * is called.
@ -255,9 +207,6 @@ public final class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {
if (handler() == null) { if (handler() == null) {
throw new IllegalStateException("handler not set"); throw new IllegalStateException("handler not set");
} }
if (channelFactory == null) {
throw new IllegalStateException("channel or channelFactory not set");
}
return this; return this;
} }
@ -281,28 +230,4 @@ public final class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {
return buf.toString(); return buf.toString();
} }
private static final class BootstrapChannelFactory<T extends Channel> implements ChannelFactory<T> {
private final Class<? extends T> clazz;
BootstrapChannelFactory(Class<? extends T> clazz) {
this.clazz = clazz;
}
@Override
public T newChannel(EventLoop eventLoop) {
try {
Constructor<? extends T> constructor = clazz.getConstructor(EventLoop.class);
return constructor.newInstance(eventLoop);
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}
@Override
public String toString() {
return StringUtil.simpleClassName(clazz) + ".class";
}
}
} }

View File

@ -16,16 +16,14 @@
package io.netty.bootstrap; package io.netty.bootstrap;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.EventLoop;
/** /**
* Factory that creates a new {@link Channel} on {@link Bootstrap#bind()}, {@link Bootstrap#connect()}, and * Factory that creates a new {@link Channel} on {@link Bootstrap#bind()}, {@link Bootstrap#connect()}, and
* {@link ServerBootstrap#bind()}. * {@link ServerBootstrap#bind()}.
*/ */
public interface ChannelFactory<T extends Channel> { public interface ChannelFactory<T extends Channel> {
/** /**
* Creates a new channel. * Creates a new channel.
*/ */
T newChannel(EventLoop eventLoop); T newChannel();
} }

View File

@ -17,24 +17,22 @@ package io.netty.bootstrap;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelConfig; import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelException; import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup; import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel; import io.netty.channel.ServerChannel;
import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.SocketChannel;
import io.netty.util.AttributeKey; import io.netty.util.AttributeKey;
import io.netty.util.concurrent.EventExecutorGroup;
import io.netty.util.internal.StringUtil; import io.netty.util.internal.StringUtil;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
import java.lang.reflect.Constructor;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -48,7 +46,6 @@ public final class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, Se
private static final InternalLogger logger = InternalLoggerFactory.getInstance(ServerBootstrap.class); private static final InternalLogger logger = InternalLoggerFactory.getInstance(ServerBootstrap.class);
private volatile ServerChannelFactory<? extends ServerChannel> channelFactory;
private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap<ChannelOption<?>, Object>(); private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap<ChannelOption<?>, Object>();
private final Map<AttributeKey<?>, Object> childAttrs = new LinkedHashMap<AttributeKey<?>, Object>(); private final Map<AttributeKey<?>, Object> childAttrs = new LinkedHashMap<AttributeKey<?>, Object>();
private volatile EventLoopGroup childGroup; private volatile EventLoopGroup childGroup;
@ -58,7 +55,6 @@ public final class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, Se
private ServerBootstrap(ServerBootstrap bootstrap) { private ServerBootstrap(ServerBootstrap bootstrap) {
super(bootstrap); super(bootstrap);
channelFactory = bootstrap.channelFactory;
childGroup = bootstrap.childGroup; childGroup = bootstrap.childGroup;
childHandler = bootstrap.childHandler; childHandler = bootstrap.childHandler;
synchronized (bootstrap.childOptions) { synchronized (bootstrap.childOptions) {
@ -69,47 +65,6 @@ public final class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, Se
} }
} }
/**
* The {@link Class} which is used to create {@link Channel} instances from.
* You either use this or {@link #channelFactory(ServerChannelFactory)} if your
* {@link Channel} implementation has no no-args constructor.
*/
public ServerBootstrap channel(Class<? extends ServerChannel> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
}
return channelFactory(new ServerBootstrapChannelFactory<ServerChannel>(channelClass));
}
/**
* {@link ChannelFactory} which is used to create {@link Channel} instances from
* when calling {@link #bind()}. This method is usually only used if {@link #channel(Class)}
* is not working for you because of some more complex needs. If your {@link Channel} implementation
* has a no-args constructor, its highly recommend to just use {@link #channel(Class)} for
* simplify your code.
*/
public ServerBootstrap channelFactory(ServerChannelFactory<? extends ServerChannel> channelFactory) {
if (channelFactory == null) {
throw new NullPointerException("channelFactory");
}
if (this.channelFactory != null) {
throw new IllegalStateException("channelFactory set already");
}
this.channelFactory = channelFactory;
return this;
}
@Override
Channel createChannel() {
EventLoop eventLoop = group().next();
return channelFactory().newChannel(eventLoop, childGroup);
}
ServerChannelFactory<? extends ServerChannel> channelFactory() {
return channelFactory;
}
/** /**
* Specify the {@link EventLoopGroup} which is used for the parent (acceptor) and the child (client). * Specify the {@link EventLoopGroup} which is used for the parent (acceptor) and the child (client).
*/ */
@ -119,8 +74,8 @@ public final class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, Se
} }
/** /**
* Set the {@link EventExecutorGroup} for the parent (acceptor) and the child (client). These * Set the {@link EventLoopGroup} for the parent (acceptor) and the child (client). These
* {@link EventExecutorGroup}'s are used to handle all the events and IO for {@link SocketChannel} and * {@link EventLoopGroup}'s are used to handle all the events and IO for {@link SocketChannel} and
* {@link Channel}'s. * {@link Channel}'s.
*/ */
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) { public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
@ -212,6 +167,7 @@ public final class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, Se
p.addLast(handler()); p.addLast(handler());
} }
final EventLoopGroup currentChildGroup = childGroup;
final ChannelHandler currentChildHandler = childHandler; final ChannelHandler currentChildHandler = childHandler;
final Entry<ChannelOption<?>, Object>[] currentChildOptions; final Entry<ChannelOption<?>, Object>[] currentChildOptions;
final Entry<AttributeKey<?>, Object>[] currentChildAttrs; final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
@ -225,8 +181,8 @@ public final class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, Se
p.addLast(new ChannelInitializer<Channel>() { p.addLast(new ChannelInitializer<Channel>() {
@Override @Override
public void initChannel(Channel ch) throws Exception { public void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new ServerBootstrapAcceptor(currentChildHandler, currentChildOptions, ch.pipeline().addLast(new ServerBootstrapAcceptor(
currentChildAttrs)); currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
} }
}); });
} }
@ -241,9 +197,6 @@ public final class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, Se
logger.warn("childGroup is not set. Using parentGroup instead."); logger.warn("childGroup is not set. Using parentGroup instead.");
childGroup = group(); childGroup = group();
} }
if (channelFactory == null) {
throw new IllegalStateException("channel or channelFactory not set");
}
return this; return this;
} }
@ -259,12 +212,16 @@ public final class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, Se
private static class ServerBootstrapAcceptor extends ChannelHandlerAdapter { private static class ServerBootstrapAcceptor extends ChannelHandlerAdapter {
private final EventLoopGroup childGroup;
private final ChannelHandler childHandler; private final ChannelHandler childHandler;
private final Entry<ChannelOption<?>, Object>[] childOptions; private final Entry<ChannelOption<?>, Object>[] childOptions;
private final Entry<AttributeKey<?>, Object>[] childAttrs; private final Entry<AttributeKey<?>, Object>[] childAttrs;
ServerBootstrapAcceptor(ChannelHandler childHandler, Entry<ChannelOption<?>, Object>[] childOptions, @SuppressWarnings("unchecked")
Entry<AttributeKey<?>, Object>[] childAttrs) { ServerBootstrapAcceptor(
EventLoopGroup childGroup, ChannelHandler childHandler,
Entry<ChannelOption<?>, Object>[] childOptions, Entry<AttributeKey<?>, Object>[] childAttrs) {
this.childGroup = childGroup;
this.childHandler = childHandler; this.childHandler = childHandler;
this.childOptions = childOptions; this.childOptions = childOptions;
this.childAttrs = childAttrs; this.childAttrs = childAttrs;
@ -273,7 +230,7 @@ public final class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, Se
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void channelRead(ChannelHandlerContext ctx, Object msg) { public void channelRead(ChannelHandlerContext ctx, Object msg) {
Channel child = (Channel) msg; final Channel child = (Channel) msg;
child.pipeline().addLast(childHandler); child.pipeline().addLast(childHandler);
@ -291,7 +248,23 @@ public final class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, Se
child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue()); child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
} }
child.unsafe().register(child.newPromise()); try {
childGroup.register(child).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
forceClose(child, future.cause());
}
}
});
} catch (Throwable t) {
forceClose(child, t);
}
}
private static void forceClose(Channel child, Throwable t) {
child.unsafe().closeForcibly();
logger.warn("Failed to register an accepted channel: " + child, t);
} }
@Override @Override
@ -358,29 +331,5 @@ public final class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, Se
return buf.toString(); return buf.toString();
} }
private static final class ServerBootstrapChannelFactory<T extends ServerChannel>
implements ServerChannelFactory<T> {
private final Class<? extends T> clazz;
ServerBootstrapChannelFactory(Class<? extends T> clazz) {
this.clazz = clazz;
} }
@Override
public T newChannel(EventLoop eventLoop, EventLoopGroup childGroup) {
try {
Constructor<? extends T> constructor = clazz.getConstructor(EventLoop.class, EventLoopGroup.class);
return constructor.newInstance(eventLoop, childGroup);
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}
@Override
public String toString() {
return StringUtil.simpleClassName(clazz) + ".class";
}
}
}

View File

@ -1,33 +0,0 @@
/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel;
/**
* Factory that creates a new {@link Channel} on {@link Bootstrap#bind()}, {@link Bootstrap#connect()}, and
* {@link ServerBootstrap#bind()}.
*/
public interface ServerChannelFactory<T extends ServerChannel> {
/**
* Creates a new channel.
*/
T newChannel(EventLoop eventLoop, EventLoopGroup childGroup);
}

View File

@ -59,7 +59,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
private volatile SocketAddress localAddress; private volatile SocketAddress localAddress;
private volatile SocketAddress remoteAddress; private volatile SocketAddress remoteAddress;
private final EventLoop eventLoop; private volatile EventLoop eventLoop;
private volatile boolean registered; private volatile boolean registered;
/** Cache for the string representation of this channel */ /** Cache for the string representation of this channel */
@ -72,9 +72,8 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
* @param parent * @param parent
* the parent of this channel. {@code null} if there's no parent. * the parent of this channel. {@code null} if there's no parent.
*/ */
protected AbstractChannel(Channel parent, EventLoop eventLoop) { protected AbstractChannel(Channel parent) {
this.parent = parent; this.parent = parent;
this.eventLoop = validate(eventLoop);
unsafe = newUnsafe(); unsafe = newUnsafe();
pipeline = new DefaultChannelPipeline(this); pipeline = new DefaultChannelPipeline(this);
} }
@ -107,6 +106,10 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
@Override @Override
public EventLoop eventLoop() { public EventLoop eventLoop() {
EventLoop eventLoop = this.eventLoop;
if (eventLoop == null) {
throw new IllegalStateException("channel not registered to an event loop");
}
return eventLoop; return eventLoop;
} }
@ -179,6 +182,11 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
return pipeline.close(); return pipeline.close();
} }
@Override
public ChannelFuture deregister() {
return pipeline.deregister();
}
@Override @Override
public Channel flush() { public Channel flush() {
pipeline.flush(); pipeline.flush();
@ -210,6 +218,11 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
return pipeline.close(promise); return pipeline.close(promise);
} }
@Override
public ChannelFuture deregister(ChannelPromise promise) {
return pipeline.deregister(promise);
}
@Override @Override
public Channel read() { public Channel read() {
pipeline.read(); pipeline.read();
@ -375,7 +388,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
@Override @Override
public final ChannelHandlerInvoker invoker() { public final ChannelHandlerInvoker invoker() {
return eventLoop.asInvoker(); return eventLoop().asInvoker();
} }
@Override @Override
@ -394,7 +407,22 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
} }
@Override @Override
public final void register(final ChannelPromise promise) { public final void register(EventLoop eventLoop, final ChannelPromise promise) {
if (eventLoop == null) {
throw new NullPointerException("eventLoop");
}
if (isRegistered()) {
promise.setFailure(new IllegalStateException("registered to an event loop already"));
return;
}
if (!isCompatible(eventLoop)) {
promise.setFailure(new IllegalStateException("incompatible event loop type: " +
eventLoop.getClass().getName()));
return;
}
AbstractChannel.this.eventLoop = eventLoop;
if (eventLoop.inEventLoop()) { if (eventLoop.inEventLoop()) {
register0(promise); register0(promise);
} else { } else {
@ -552,7 +580,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
}); });
} }
deregister(); deregister(voidPromise());
} }
} }
@ -565,8 +593,14 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
} }
} }
private void deregister() { @Override
public final void deregister(final ChannelPromise promise) {
if (!promise.setUncancellable()) {
return;
}
if (!registered) { if (!registered) {
safeSetSuccess(promise);
return; return;
} }
@ -577,6 +611,18 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
} finally { } finally {
if (registered) { if (registered) {
registered = false; registered = false;
invokeLater(new OneTimeTask() {
@Override
public void run() {
pipeline.fireChannelUnregistered();
}
});
safeSetSuccess(promise);
} else {
// Some transports like local and AIO does not allow the deregistration of
// an open channel. Their doDeregister() calls close(). Consequently,
// close() calls deregister() again - no need to fire channelUnregistered.
safeSetSuccess(promise);
} }
} }
} }
@ -718,16 +764,6 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
} }
} }
private EventLoop validate(EventLoop eventLoop) {
if (eventLoop == null) {
throw new IllegalStateException("null event loop");
}
if (!isCompatible(eventLoop)) {
throw new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName());
}
return eventLoop;
}
/** /**
* Create a new {@link ChannelOutboundBuffer} which holds the pending messages for this {@link AbstractChannel}. * Create a new {@link ChannelOutboundBuffer} which holds the pending messages for this {@link AbstractChannel}.
*/ */

View File

@ -34,14 +34,11 @@ public abstract class AbstractServerChannel extends AbstractChannel implements S
private static final ChannelMetadata METADATA = new ChannelMetadata(false); private static final ChannelMetadata METADATA = new ChannelMetadata(false);
private final EventLoopGroup childGroup;
/** /**
* Creates a new instance. * Creates a new instance.
*/ */
protected AbstractServerChannel(EventLoop eventLoop, EventLoopGroup childGroup) { protected AbstractServerChannel() {
super(null, eventLoop); super(null);
this.childGroup = childGroup;
} }
@Override @Override
@ -74,11 +71,6 @@ public abstract class AbstractServerChannel extends AbstractChannel implements S
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public EventLoopGroup childEventLoopGroup() {
return childGroup;
}
private final class DefaultServerUnsafe extends AbstractUnsafe { private final class DefaultServerUnsafe extends AbstractUnsafe {
@Override @Override
public void write(Object msg, ChannelPromise promise) { public void write(Object msg, ChannelPromise promise) {

View File

@ -280,6 +280,19 @@ public interface Channel extends AttributeMap, Comparable<Channel> {
*/ */
ChannelFuture close(); ChannelFuture close();
/**
* Request to deregister this {@link Channel} from the previous assigned {@link EventLoop} and notify the
* {@link ChannelFuture} once the operation completes, either because the operation was successful or because of
* an error.
* <p>
* This will result in having the
* {@link ChannelHandler#deregister(ChannelHandlerContext, ChannelPromise)}
* method called of the next {@link ChannelHandler} contained in the {@link ChannelPipeline} of the
* {@link Channel}.
*
*/
ChannelFuture deregister();
/** /**
* Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation
* completes, either because the operation was successful or because of an error. * completes, either because the operation was successful or because of an error.
@ -353,6 +366,20 @@ public interface Channel extends AttributeMap, Comparable<Channel> {
*/ */
ChannelFuture close(ChannelPromise promise); ChannelFuture close(ChannelPromise promise);
/**
* Request to deregister this {@link Channel} from the previous assigned {@link EventLoop} and notify the
* {@link ChannelFuture} once the operation completes, either because the operation was successful or because of
* an error.
*
* The given {@link ChannelPromise} will be notified.
* <p>
* This will result in having the
* {@link ChannelHandler#deregister(ChannelHandlerContext, ChannelPromise)}
* method called of the next {@link ChannelHandler} contained in the {@link ChannelPipeline} of the
* {@link Channel}.
*/
ChannelFuture deregister(ChannelPromise promise);
/** /**
* Request to Read data from the {@link Channel} into the first inbound buffer, triggers an * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an
* {@link ChannelHandler#channelRead(ChannelHandlerContext, Object)} event if data was * {@link ChannelHandler#channelRead(ChannelHandlerContext, Object)} event if data was
@ -406,6 +433,7 @@ public interface Channel extends AttributeMap, Comparable<Channel> {
* <li>{@link #remoteAddress()}</li> * <li>{@link #remoteAddress()}</li>
* <li>{@link #closeForcibly()}</li> * <li>{@link #closeForcibly()}</li>
* <li>{@link #register(ChannelPromise)}</li> * <li>{@link #register(ChannelPromise)}</li>
* <li>{@link #deregister(ChannelPromise)}</li>
* <li>{@link #voidPromise()}</li> * <li>{@link #voidPromise()}</li>
* </ul> * </ul>
*/ */
@ -432,7 +460,7 @@ public interface Channel extends AttributeMap, Comparable<Channel> {
* Register the {@link Channel} of the {@link ChannelPromise} and notify * Register the {@link Channel} of the {@link ChannelPromise} and notify
* the {@link ChannelFuture} once the registration was complete. * the {@link ChannelFuture} once the registration was complete.
*/ */
void register(ChannelPromise promise); void register(EventLoop eventLoop, ChannelPromise promise);
/** /**
* Bind the {@link SocketAddress} to the {@link Channel} of the {@link ChannelPromise} and notify * Bind the {@link SocketAddress} to the {@link Channel} of the {@link ChannelPromise} and notify
@ -467,6 +495,12 @@ public interface Channel extends AttributeMap, Comparable<Channel> {
*/ */
void closeForcibly(); void closeForcibly();
/**
* Deregister the {@link Channel} of the {@link ChannelPromise} from {@link EventLoop} and notify the
* {@link ChannelPromise} once the operation was complete.
*/
void deregister(ChannelPromise promise);
/** /**
* Schedules a read operation that fills the inbound buffer of the first {@link ChannelHandler} in the * Schedules a read operation that fills the inbound buffer of the first {@link ChannelHandler} in the
* {@link ChannelPipeline}. If there's already a pending read operation, this method does nothing. * {@link ChannelPipeline}. If there's already a pending read operation, this method does nothing.

View File

@ -196,6 +196,11 @@ public interface ChannelHandler {
*/ */
void channelRegistered(ChannelHandlerContext ctx) throws Exception; void channelRegistered(ChannelHandlerContext ctx) throws Exception;
/**
* The {@link Channel} of the {@link ChannelHandlerContext} was unregistered from its {@link EventLoop}
*/
void channelUnregistered(ChannelHandlerContext ctx) throws Exception;
/** /**
* The {@link Channel} of the {@link ChannelHandlerContext} is now active * The {@link Channel} of the {@link ChannelHandlerContext} is now active
*/ */
@ -276,6 +281,15 @@ public interface ChannelHandler {
*/ */
void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception; void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception;
/**
* Called once a deregister operation is made from the current registered {@link EventLoop}.
*
* @param ctx the {@link ChannelHandlerContext} for which the close operation is made
* @param promise the {@link ChannelPromise} to notify once the operation completes
* @throws Exception thrown if an error accour
*/
void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception;
/** /**
* Intercepts {@link ChannelHandlerContext#read()}. * Intercepts {@link ChannelHandlerContext#read()}.
*/ */

View File

@ -102,6 +102,18 @@ public class ChannelHandlerAdapter implements ChannelHandler {
ctx.fireChannelRegistered(); ctx.fireChannelRegistered();
} }
/**
* Calls {@link ChannelHandlerContext#fireChannelRegistered()} to forward
* to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
*
* Sub-classes may override this method to change behavior.
*/
@Skip
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
ctx.fireChannelUnregistered();
}
/** /**
* Calls {@link ChannelHandlerContext#fireChannelActive()} to forward * Calls {@link ChannelHandlerContext#fireChannelActive()} to forward
* to the next {@link ChannelHandler} in the {@link ChannelPipeline}. * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
@ -224,6 +236,18 @@ public class ChannelHandlerAdapter implements ChannelHandler {
ctx.close(promise); ctx.close(promise);
} }
/**
* Calls {@link ChannelHandlerContext#deregister(ChannelPromise)} to forward
* to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
*
* Sub-classes may override this method to change behavior.
*/
@Skip
@Override
public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
ctx.deregister(promise);
}
/** /**
* Calls {@link ChannelHandlerContext#read()} to forward * Calls {@link ChannelHandlerContext#read()} to forward
* to the next {@link ChannelHandler} in the {@link ChannelPipeline}. * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.

View File

@ -192,7 +192,10 @@ public class ChannelHandlerAppender extends ChannelHandlerAdapter {
} else { } else {
name = e.name; name = e.name;
} }
pipeline.addAfter(ctx.invoker(), oldName, name, e.handler); // Pass in direct the invoker to eliminate the possibility of an IllegalStateException
// if the Channel is not registered yet.
DefaultChannelHandlerContext context = (DefaultChannelHandlerContext) ctx;
pipeline.addAfter(context.invoker, oldName, name, e.handler);
} }
} finally { } finally {
if (selfRemoval) { if (selfRemoval) {

View File

@ -175,6 +175,15 @@ public interface ChannelHandlerContext extends AttributeMap {
*/ */
ChannelHandlerContext fireChannelRegistered(); ChannelHandlerContext fireChannelRegistered();
/**
* A {@link Channel} was unregistered from its {@link EventLoop}.
*
* This will result in having the {@link ChannelHandler#channelUnregistered(ChannelHandlerContext)} method
* called of the next {@link ChannelHandler} contained in the {@link ChannelPipeline} of the
* {@link Channel}.
*/
ChannelHandlerContext fireChannelUnregistered();
/** /**
* A {@link Channel} is active now, which means it is connected. * A {@link Channel} is active now, which means it is connected.
* *
@ -295,6 +304,19 @@ public interface ChannelHandlerContext extends AttributeMap {
*/ */
ChannelFuture close(); ChannelFuture close();
/**
* Request to deregister from the previous assigned {@link EventExecutor} and notify the
* {@link ChannelFuture} once the operation completes, either because the operation was successful or because of
* an error.
* <p>
* This will result in having the
* {@link ChannelHandler#deregister(ChannelHandlerContext, ChannelPromise)}
* method called of the next {@link ChannelHandler} contained in the {@link ChannelPipeline} of the
* {@link Channel}.
*
*/
ChannelFuture deregister();
/** /**
* Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation
* completes, either because the operation was successful or because of an error. * completes, either because the operation was successful or because of an error.
@ -368,6 +390,20 @@ public interface ChannelHandlerContext extends AttributeMap {
*/ */
ChannelFuture close(ChannelPromise promise); ChannelFuture close(ChannelPromise promise);
/**
* Request to deregister from the previous assigned {@link EventExecutor} and notify the
* {@link ChannelFuture} once the operation completes, either because the operation was successful or because of
* an error.
*
* The given {@link ChannelPromise} will be notified.
* <p>
* This will result in having the
* {@link ChannelHandler#deregister(ChannelHandlerContext, ChannelPromise)}
* method called of the next {@link ChannelHandler} contained in the {@link ChannelPipeline} of the
* {@link Channel}.
*/
ChannelFuture deregister(ChannelPromise promise);
/** /**
* Request to Read data from the {@link Channel} into the first inbound buffer, triggers an * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an
* {@link ChannelHandler#channelRead(ChannelHandlerContext, Object)} event if data was * {@link ChannelHandler#channelRead(ChannelHandlerContext, Object)} event if data was

View File

@ -39,6 +39,13 @@ public interface ChannelHandlerInvoker {
*/ */
void invokeChannelRegistered(ChannelHandlerContext ctx); void invokeChannelRegistered(ChannelHandlerContext ctx);
/**
* Invokes {@link ChannelHandler#channelUnregistered(ChannelHandlerContext)}. This method is not for a user
* but for the internal {@link ChannelHandlerContext} implementation. To trigger an event, use the methods in
* {@link ChannelHandlerContext} instead.
*/
void invokeChannelUnregistered(ChannelHandlerContext ctx);
/** /**
* Invokes {@link ChannelHandler#channelActive(ChannelHandlerContext)}. This method is not for a user * Invokes {@link ChannelHandler#channelActive(ChannelHandlerContext)}. This method is not for a user
* but for the internal {@link ChannelHandlerContext} implementation. To trigger an event, use the methods in * but for the internal {@link ChannelHandlerContext} implementation. To trigger an event, use the methods in
@ -118,6 +125,13 @@ public interface ChannelHandlerInvoker {
*/ */
void invokeClose(ChannelHandlerContext ctx, ChannelPromise promise); void invokeClose(ChannelHandlerContext ctx, ChannelPromise promise);
/**
* Invokes {@link ChannelHandler#deregister(ChannelHandlerContext, ChannelPromise)}.
* This method is not for a user but for the internal {@link ChannelHandlerContext} implementation.
* To trigger an event, use the methods in {@link ChannelHandlerContext} instead.
*/
void invokeDeregister(ChannelHandlerContext ctx, ChannelPromise promise);
/** /**
* Invokes {@link ChannelHandler#read(ChannelHandlerContext)}. * Invokes {@link ChannelHandler#read(ChannelHandlerContext)}.
* This method is not for a user but for the internal {@link ChannelHandlerContext} implementation. * This method is not for a user but for the internal {@link ChannelHandlerContext} implementation.

View File

@ -35,6 +35,14 @@ public final class ChannelHandlerInvokerUtil {
} }
} }
public static void invokeChannelUnregisteredNow(ChannelHandlerContext ctx) {
try {
ctx.handler().channelUnregistered(ctx);
} catch (Throwable t) {
notifyHandlerException(ctx, t);
}
}
public static void invokeChannelActiveNow(final ChannelHandlerContext ctx) { public static void invokeChannelActiveNow(final ChannelHandlerContext ctx) {
try { try {
ctx.handler().channelActive(ctx); ctx.handler().channelActive(ctx);
@ -129,6 +137,14 @@ public final class ChannelHandlerInvokerUtil {
} }
} }
public static void invokeDeregisterNow(final ChannelHandlerContext ctx, final ChannelPromise promise) {
try {
ctx.handler().deregister(ctx, promise);
} catch (Throwable t) {
notifyOutboundHandlerException(t, promise);
}
}
public static void invokeReadNow(final ChannelHandlerContext ctx) { public static void invokeReadNow(final ChannelHandlerContext ctx) {
try { try {
ctx.handler().read(ctx); ctx.handler().read(ctx);

View File

@ -17,6 +17,7 @@ package io.netty.channel;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.util.concurrent.DefaultEventExecutorGroup; import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.EventExecutorGroup; import io.netty.util.concurrent.EventExecutorGroup;
import java.net.ConnectException; import java.net.ConnectException;
@ -661,6 +662,15 @@ public interface ChannelPipeline extends Iterable<Entry<String, ChannelHandler>>
*/ */
ChannelPipeline fireChannelRegistered(); ChannelPipeline fireChannelRegistered();
/**
* A {@link Channel} was unregistered from its {@link EventLoop}.
*
* This will result in having the {@link ChannelHandler#channelUnregistered(ChannelHandlerContext)} method
* called of the next {@link ChannelHandler} contained in the {@link ChannelPipeline} of the
* {@link Channel}.
*/
ChannelPipeline fireChannelUnregistered();
/** /**
* A {@link Channel} is active now, which means it is connected. * A {@link Channel} is active now, which means it is connected.
* *
@ -781,6 +791,19 @@ public interface ChannelPipeline extends Iterable<Entry<String, ChannelHandler>>
*/ */
ChannelFuture close(); ChannelFuture close();
/**
* Request to deregister the {@link Channel} from the previous assigned {@link EventExecutor} and notify the
* {@link ChannelFuture} once the operation completes, either because the operation was successful or because of
* an error.
* <p>
* This will result in having the
* {@link ChannelHandler#deregister(ChannelHandlerContext, ChannelPromise)}
* method called of the next {@link ChannelHandler} contained in the {@link ChannelPipeline} of the
* {@link Channel}.
*
*/
ChannelFuture deregister();
/** /**
* Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation
* completes, either because the operation was successful or because of an error. * completes, either because the operation was successful or because of an error.
@ -854,6 +877,20 @@ public interface ChannelPipeline extends Iterable<Entry<String, ChannelHandler>>
*/ */
ChannelFuture close(ChannelPromise promise); ChannelFuture close(ChannelPromise promise);
/**
* Request to deregister the {@link Channel} bound this {@link ChannelPipeline} from the previous assigned
* {@link EventExecutor} and notify the {@link ChannelFuture} once the operation completes, either because the
* operation was successful or because of an error.
*
* The given {@link ChannelPromise} will be notified.
* <p>ChannelOutboundHandler
* This will result in having the
* {@link ChannelHandler#deregister(ChannelHandlerContext, ChannelPromise)}
* method called of the next {@link ChannelHandler} contained in the {@link ChannelPipeline} of the
* {@link Channel}.
*/
ChannelFuture deregister(ChannelPromise promise);
/** /**
* Request to Read data from the {@link Channel} into the first inbound buffer, triggers an * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an
* {@link ChannelHandler#channelRead(ChannelHandlerContext, Object)} event if data was * {@link ChannelHandler#channelRead(ChannelHandlerContext, Object)} event if data was

View File

@ -38,19 +38,21 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou
static final int MASK_HANDLER_REMOVED = 1 << 1; static final int MASK_HANDLER_REMOVED = 1 << 1;
private static final int MASK_EXCEPTION_CAUGHT = 1 << 2; private static final int MASK_EXCEPTION_CAUGHT = 1 << 2;
private static final int MASK_CHANNEL_REGISTERED = 1 << 3; private static final int MASK_CHANNEL_REGISTERED = 1 << 3;
private static final int MASK_CHANNEL_ACTIVE = 1 << 4; private static final int MASK_CHANNEL_UNREGISTERED = 1 << 4;
private static final int MASK_CHANNEL_INACTIVE = 1 << 5; private static final int MASK_CHANNEL_ACTIVE = 1 << 5;
private static final int MASK_CHANNEL_READ = 1 << 6; private static final int MASK_CHANNEL_INACTIVE = 1 << 6;
private static final int MASK_CHANNEL_READ_COMPLETE = 1 << 7; private static final int MASK_CHANNEL_READ = 1 << 7;
private static final int MASK_CHANNEL_WRITABILITY_CHANGED = 1 << 8; private static final int MASK_CHANNEL_READ_COMPLETE = 1 << 8;
private static final int MASK_USER_EVENT_TRIGGERED = 1 << 9; private static final int MASK_CHANNEL_WRITABILITY_CHANGED = 1 << 9;
private static final int MASK_BIND = 1 << 10; private static final int MASK_USER_EVENT_TRIGGERED = 1 << 10;
private static final int MASK_CONNECT = 1 << 11; private static final int MASK_BIND = 1 << 11;
private static final int MASK_DISCONNECT = 1 << 12; private static final int MASK_CONNECT = 1 << 12;
private static final int MASK_CLOSE = 1 << 13; private static final int MASK_DISCONNECT = 1 << 13;
private static final int MASK_READ = 1 << 14; private static final int MASK_CLOSE = 1 << 14;
private static final int MASK_WRITE = 1 << 15; private static final int MASK_DEREGISTER = 1 << 15;
private static final int MASK_FLUSH = 1 << 16; private static final int MASK_READ = 1 << 16;
private static final int MASK_WRITE = 1 << 17;
private static final int MASK_FLUSH = 1 << 18;
/** /**
* Cache the result of the costly generation of {@link #skipFlags} in the partitioned synchronized * Cache the result of the costly generation of {@link #skipFlags} in the partitioned synchronized
@ -111,6 +113,10 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou
"channelRegistered", ChannelHandlerContext.class).isAnnotationPresent(Skip.class)) { "channelRegistered", ChannelHandlerContext.class).isAnnotationPresent(Skip.class)) {
flags |= MASK_CHANNEL_REGISTERED; flags |= MASK_CHANNEL_REGISTERED;
} }
if (handlerType.getMethod(
"channelUnregistered", ChannelHandlerContext.class).isAnnotationPresent(Skip.class)) {
flags |= MASK_CHANNEL_UNREGISTERED;
}
if (handlerType.getMethod( if (handlerType.getMethod(
"channelActive", ChannelHandlerContext.class).isAnnotationPresent(Skip.class)) { "channelActive", ChannelHandlerContext.class).isAnnotationPresent(Skip.class)) {
flags |= MASK_CHANNEL_ACTIVE; flags |= MASK_CHANNEL_ACTIVE;
@ -153,6 +159,10 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou
"close", ChannelHandlerContext.class, ChannelPromise.class).isAnnotationPresent(Skip.class)) { "close", ChannelHandlerContext.class, ChannelPromise.class).isAnnotationPresent(Skip.class)) {
flags |= MASK_CLOSE; flags |= MASK_CLOSE;
} }
if (handlerType.getMethod(
"deregister", ChannelHandlerContext.class, ChannelPromise.class).isAnnotationPresent(Skip.class)) {
flags |= MASK_DEREGISTER;
}
if (handlerType.getMethod( if (handlerType.getMethod(
"read", ChannelHandlerContext.class).isAnnotationPresent(Skip.class)) { "read", ChannelHandlerContext.class).isAnnotationPresent(Skip.class)) {
flags |= MASK_READ; flags |= MASK_READ;
@ -215,14 +225,9 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou
this.pipeline = pipeline; this.pipeline = pipeline;
this.name = name; this.name = name;
this.handler = handler; this.handler = handler;
this.invoker = invoker;
skipFlags = skipFlags(handler); skipFlags = skipFlags(handler);
if (invoker == null) {
this.invoker = channel.unsafe().invoker();
} else {
this.invoker = invoker;
}
} }
/** Invocation initiated by {@link DefaultChannelPipeline#teardownAll()}}. */ /** Invocation initiated by {@link DefaultChannelPipeline#teardownAll()}}. */
@ -267,11 +272,14 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou
@Override @Override
public EventExecutor executor() { public EventExecutor executor() {
return invoker.executor(); return invoker().executor();
} }
@Override @Override
public ChannelHandlerInvoker invoker() { public ChannelHandlerInvoker invoker() {
if (invoker == null) {
return channel.unsafe().invoker();
}
return invoker; return invoker;
} }
@ -293,35 +301,42 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou
@Override @Override
public ChannelHandlerContext fireChannelRegistered() { public ChannelHandlerContext fireChannelRegistered() {
DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_REGISTERED); DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_REGISTERED);
next.invoker.invokeChannelRegistered(next); next.invoker().invokeChannelRegistered(next);
return this;
}
@Override
public ChannelHandlerContext fireChannelUnregistered() {
DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_UNREGISTERED);
next.invoker().invokeChannelUnregistered(next);
return this; return this;
} }
@Override @Override
public ChannelHandlerContext fireChannelActive() { public ChannelHandlerContext fireChannelActive() {
DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_ACTIVE); DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_ACTIVE);
next.invoker.invokeChannelActive(next); next.invoker().invokeChannelActive(next);
return this; return this;
} }
@Override @Override
public ChannelHandlerContext fireChannelInactive() { public ChannelHandlerContext fireChannelInactive() {
DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_INACTIVE); DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_INACTIVE);
next.invoker.invokeChannelInactive(next); next.invoker().invokeChannelInactive(next);
return this; return this;
} }
@Override @Override
public ChannelHandlerContext fireExceptionCaught(Throwable cause) { public ChannelHandlerContext fireExceptionCaught(Throwable cause) {
DefaultChannelHandlerContext next = findContextInbound(MASK_EXCEPTION_CAUGHT); DefaultChannelHandlerContext next = findContextInbound(MASK_EXCEPTION_CAUGHT);
next.invoker.invokeExceptionCaught(next, cause); next.invoker().invokeExceptionCaught(next, cause);
return this; return this;
} }
@Override @Override
public ChannelHandlerContext fireUserEventTriggered(Object event) { public ChannelHandlerContext fireUserEventTriggered(Object event) {
DefaultChannelHandlerContext next = findContextInbound(MASK_USER_EVENT_TRIGGERED); DefaultChannelHandlerContext next = findContextInbound(MASK_USER_EVENT_TRIGGERED);
next.invoker.invokeUserEventTriggered(next, event); next.invoker().invokeUserEventTriggered(next, event);
return this; return this;
} }
@ -329,21 +344,21 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou
public ChannelHandlerContext fireChannelRead(Object msg) { public ChannelHandlerContext fireChannelRead(Object msg) {
DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_READ); DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_READ);
ReferenceCountUtil.touch(msg, next); ReferenceCountUtil.touch(msg, next);
next.invoker.invokeChannelRead(next, msg); next.invoker().invokeChannelRead(next, msg);
return this; return this;
} }
@Override @Override
public ChannelHandlerContext fireChannelReadComplete() { public ChannelHandlerContext fireChannelReadComplete() {
DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_READ_COMPLETE); DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_READ_COMPLETE);
next.invoker.invokeChannelReadComplete(next); next.invoker().invokeChannelReadComplete(next);
return this; return this;
} }
@Override @Override
public ChannelHandlerContext fireChannelWritabilityChanged() { public ChannelHandlerContext fireChannelWritabilityChanged() {
DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_WRITABILITY_CHANGED); DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_WRITABILITY_CHANGED);
next.invoker.invokeChannelWritabilityChanged(next); next.invoker().invokeChannelWritabilityChanged(next);
return this; return this;
} }
@ -372,10 +387,15 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou
return close(newPromise()); return close(newPromise());
} }
@Override
public ChannelFuture deregister() {
return deregister(newPromise());
}
@Override @Override
public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) { public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) {
DefaultChannelHandlerContext next = findContextOutbound(MASK_BIND); DefaultChannelHandlerContext next = findContextOutbound(MASK_BIND);
next.invoker.invokeBind(next, localAddress, promise); next.invoker().invokeBind(next, localAddress, promise);
return promise; return promise;
} }
@ -387,7 +407,7 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou
@Override @Override
public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) { public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
DefaultChannelHandlerContext next = findContextOutbound(MASK_CONNECT); DefaultChannelHandlerContext next = findContextOutbound(MASK_CONNECT);
next.invoker.invokeConnect(next, remoteAddress, localAddress, promise); next.invoker().invokeConnect(next, remoteAddress, localAddress, promise);
return promise; return promise;
} }
@ -398,21 +418,28 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou
} }
DefaultChannelHandlerContext next = findContextOutbound(MASK_DISCONNECT); DefaultChannelHandlerContext next = findContextOutbound(MASK_DISCONNECT);
next.invoker.invokeDisconnect(next, promise); next.invoker().invokeDisconnect(next, promise);
return promise; return promise;
} }
@Override @Override
public ChannelFuture close(ChannelPromise promise) { public ChannelFuture close(ChannelPromise promise) {
DefaultChannelHandlerContext next = findContextOutbound(MASK_CLOSE); DefaultChannelHandlerContext next = findContextOutbound(MASK_CLOSE);
next.invoker.invokeClose(next, promise); next.invoker().invokeClose(next, promise);
return promise;
}
@Override
public ChannelFuture deregister(ChannelPromise promise) {
DefaultChannelHandlerContext next = findContextOutbound(MASK_DEREGISTER);
next.invoker().invokeDeregister(next, promise);
return promise; return promise;
} }
@Override @Override
public ChannelHandlerContext read() { public ChannelHandlerContext read() {
DefaultChannelHandlerContext next = findContextOutbound(MASK_READ); DefaultChannelHandlerContext next = findContextOutbound(MASK_READ);
next.invoker.invokeRead(next); next.invoker().invokeRead(next);
return this; return this;
} }
@ -425,14 +452,14 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou
public ChannelFuture write(Object msg, ChannelPromise promise) { public ChannelFuture write(Object msg, ChannelPromise promise) {
DefaultChannelHandlerContext next = findContextOutbound(MASK_WRITE); DefaultChannelHandlerContext next = findContextOutbound(MASK_WRITE);
ReferenceCountUtil.touch(msg, next); ReferenceCountUtil.touch(msg, next);
next.invoker.invokeWrite(next, msg, promise); next.invoker().invokeWrite(next, msg, promise);
return promise; return promise;
} }
@Override @Override
public ChannelHandlerContext flush() { public ChannelHandlerContext flush() {
DefaultChannelHandlerContext next = findContextOutbound(MASK_FLUSH); DefaultChannelHandlerContext next = findContextOutbound(MASK_FLUSH);
next.invoker.invokeFlush(next); next.invoker().invokeFlush(next);
return this; return this;
} }
@ -441,9 +468,9 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou
DefaultChannelHandlerContext next; DefaultChannelHandlerContext next;
next = findContextOutbound(MASK_WRITE); next = findContextOutbound(MASK_WRITE);
ReferenceCountUtil.touch(msg, next); ReferenceCountUtil.touch(msg, next);
next.invoker.invokeWrite(next, msg, promise); next.invoker().invokeWrite(next, msg, promise);
next = findContextOutbound(MASK_FLUSH); next = findContextOutbound(MASK_FLUSH);
next.invoker.invokeFlush(next); next.invoker().invokeFlush(next);
return promise; return promise;
} }

View File

@ -57,6 +57,20 @@ public class DefaultChannelHandlerInvoker implements ChannelHandlerInvoker {
} }
} }
@Override
public void invokeChannelUnregistered(final ChannelHandlerContext ctx) {
if (executor.inEventLoop()) {
invokeChannelUnregisteredNow(ctx);
} else {
executor.execute(new OneTimeTask() {
@Override
public void run() {
invokeChannelUnregisteredNow(ctx);
}
});
}
}
@Override @Override
public void invokeChannelActive(final ChannelHandlerContext ctx) { public void invokeChannelActive(final ChannelHandlerContext ctx) {
if (executor.inEventLoop()) { if (executor.inEventLoop()) {
@ -269,6 +283,25 @@ public class DefaultChannelHandlerInvoker implements ChannelHandlerInvoker {
} }
} }
@Override
public void invokeDeregister(final ChannelHandlerContext ctx, final ChannelPromise promise) {
if (!validatePromise(ctx, promise, false)) {
// promise cancelled
return;
}
if (executor.inEventLoop()) {
invokeDeregisterNow(ctx, promise);
} else {
safeExecuteOutbound(new OneTimeTask() {
@Override
public void run() {
invokeDeregisterNow(ctx, promise);
}
}, promise);
}
}
@Override @Override
public void invokeRead(final ChannelHandlerContext ctx) { public void invokeRead(final ChannelHandlerContext ctx) {
if (executor.inEventLoop()) { if (executor.inEventLoop()) {

View File

@ -550,6 +550,7 @@ final class DefaultChannelPipeline implements ChannelPipeline {
try { try {
ctx.handler().handlerAdded(ctx); ctx.handler().handlerAdded(ctx);
} catch (Throwable t) { } catch (Throwable t) {
t.printStackTrace();
boolean removed = false; boolean removed = false;
try { try {
remove(ctx); remove(ctx);
@ -802,6 +803,17 @@ final class DefaultChannelPipeline implements ChannelPipeline {
return this; return this;
} }
@Override
public ChannelPipeline fireChannelUnregistered() {
head.fireChannelUnregistered();
// Remove all handlers sequentially if channel is closed and unregistered.
if (!channel.isOpen()) {
teardownAll();
}
return this;
}
/** /**
* Removes all handlers from the pipeline one by one from tail (exclusive) to head (inclusive) to trigger * Removes all handlers from the pipeline one by one from tail (exclusive) to head (inclusive) to trigger
* handlerRemoved(). Note that the tail handler is excluded because it's neither an outbound handler nor it * handlerRemoved(). Note that the tail handler is excluded because it's neither an outbound handler nor it
@ -825,7 +837,6 @@ final class DefaultChannelPipeline implements ChannelPipeline {
@Override @Override
public ChannelPipeline fireChannelInactive() { public ChannelPipeline fireChannelInactive() {
head.fireChannelInactive(); head.fireChannelInactive();
teardownAll();
return this; return this;
} }
@ -887,6 +898,11 @@ final class DefaultChannelPipeline implements ChannelPipeline {
return tail.close(); return tail.close();
} }
@Override
public ChannelFuture deregister() {
return tail.deregister();
}
@Override @Override
public ChannelPipeline flush() { public ChannelPipeline flush() {
tail.flush(); tail.flush();
@ -918,6 +934,11 @@ final class DefaultChannelPipeline implements ChannelPipeline {
return tail.close(promise); return tail.close(promise);
} }
@Override
public ChannelFuture deregister(ChannelPromise promise) {
return tail.close(promise);
}
@Override @Override
public ChannelPipeline read() { public ChannelPipeline read() {
tail.read(); tail.read();
@ -983,6 +1004,9 @@ final class DefaultChannelPipeline implements ChannelPipeline {
@Override @Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception { } public void channelRegistered(ChannelHandlerContext ctx) throws Exception { }
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { }
@Override @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception { } public void channelActive(ChannelHandlerContext ctx) throws Exception { }
@ -1050,6 +1074,11 @@ final class DefaultChannelPipeline implements ChannelPipeline {
unsafe.close(promise); unsafe.close(promise);
} }
@Override
public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
unsafe.deregister(promise);
}
@Override @Override
public void read(ChannelHandlerContext ctx) { public void read(ChannelHandlerContext ctx) {
unsafe.beginRead(); unsafe.beginRead();

View File

@ -25,4 +25,16 @@ import io.netty.util.concurrent.EventExecutorGroup;
public interface EventLoopGroup extends EventExecutorGroup { public interface EventLoopGroup extends EventExecutorGroup {
@Override @Override
EventLoop next(); EventLoop next();
/**
* Register a {@link Channel} with this {@link EventLoop}. The returned {@link ChannelFuture}
* will get notified once the registration was complete.
*/
ChannelFuture register(Channel channel);
/**
* Register a {@link Channel} with this {@link EventLoop}. The passed {@link ChannelFuture}
* will get notified once the registration was complete and also will get returned.
*/
ChannelFuture register(Channel channel, ChannelPromise promise);
} }

View File

@ -69,5 +69,12 @@ public abstract class MultithreadEventLoopGroup extends MultithreadEventExecutor
} }
@Override @Override
protected abstract EventLoop newChild(Executor executor, Object... args) throws Exception; public ChannelFuture register(Channel channel) {
return next().register(channel);
}
@Override
public ChannelFuture register(Channel channel, ChannelPromise promise) {
return next().register(channel, promise);
}
} }

View File

@ -18,9 +18,8 @@ package io.netty.channel;
import io.netty.channel.socket.ServerSocketChannel; import io.netty.channel.socket.ServerSocketChannel;
/** /**
* A {@link Channel} that accepts an incoming connection attempt and creates its child {@link Channel}s by accepting * A {@link Channel} that accepts an incoming connection attempt and creates
* them. {@link ServerSocketChannel} is a good example. * its child {@link Channel}s by accepting them. {@link ServerSocketChannel} is
* a good example.
*/ */
public interface ServerChannel extends Channel { public interface ServerChannel extends Channel { }
EventLoopGroup childEventLoopGroup();
}

View File

@ -51,6 +51,24 @@ public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor im
return invoker; return invoker;
} }
@Override
public ChannelFuture register(Channel channel) {
return register(channel, new DefaultChannelPromise(channel, this));
}
@Override
public ChannelFuture register(final Channel channel, final ChannelPromise promise) {
if (channel == null) {
throw new NullPointerException("channel");
}
if (promise == null) {
throw new NullPointerException("promise");
}
channel.unsafe().register(this, promise);
return promise;
}
@Override @Override
protected boolean wakesUpForTask(Runnable task) { protected boolean wakesUpForTask(Runnable task) {
return !(task instanceof NonWakeupRunnable); return !(task instanceof NonWakeupRunnable);

View File

@ -30,6 +30,21 @@ public class ThreadPerChannelEventLoop extends SingleThreadEventLoop {
this.parent = parent; this.parent = parent;
} }
@Override
public ChannelFuture register(Channel channel, ChannelPromise promise) {
return super.register(channel, promise).addListener(new ChannelFutureListener() {
@Override
@SuppressWarnings("unchecked")
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
ch = future.channel();
} else {
deregister();
}
}
});
}
@Override @Override
protected void run() { protected void run() {
for (;;) { for (;;) {

View File

@ -16,6 +16,7 @@
package io.netty.channel; package io.netty.channel;
import io.netty.util.concurrent.AbstractEventExecutorGroup;
import io.netty.util.concurrent.DefaultPromise; import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.EventExecutor; import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.Future; import io.netty.util.concurrent.Future;
@ -39,13 +40,14 @@ import java.util.concurrent.TimeUnit;
/** /**
* An {@link EventLoopGroup} that creates one {@link EventLoop} per {@link Channel}. * An {@link EventLoopGroup} that creates one {@link EventLoop} per {@link Channel}.
*/ */
public class ThreadPerChannelEventLoopGroup extends AbstractEventLoopGroup { public class ThreadPerChannelEventLoopGroup extends AbstractEventExecutorGroup implements EventLoopGroup {
private final Object[] childArgs; private final Object[] childArgs;
private final int maxChannels; private final int maxChannels;
final Executor executor; final Executor executor;
final Set<EventLoop> activeChildren = final Set<EventLoop> activeChildren =
Collections.newSetFromMap(PlatformDependent.<EventLoop, Boolean>newConcurrentHashMap()); Collections.newSetFromMap(PlatformDependent.<EventLoop, Boolean>newConcurrentHashMap());
private final Set<EventLoop> readOnlyActiveChildren = Collections.unmodifiableSet(activeChildren);
final Queue<EventLoop> idleChildren = new ConcurrentLinkedQueue<EventLoop>(); final Queue<EventLoop> idleChildren = new ConcurrentLinkedQueue<EventLoop>();
private final ChannelException tooManyChannels; private final ChannelException tooManyChannels;
@ -73,7 +75,9 @@ public class ThreadPerChannelEventLoopGroup extends AbstractEventLoopGroup {
* *
* @param maxChannels the maximum number of channels to handle with this instance. Once you try to register * @param maxChannels the maximum number of channels to handle with this instance. Once you try to register
* a new {@link Channel} and the maximum is exceed it will throw an * a new {@link Channel} and the maximum is exceed it will throw an
* {@link ChannelException}. Use {@code 0} to use no limit * {@link ChannelException}. on the {@link #register(Channel)} and
* {@link #register(Channel, ChannelPromise)} method.
* Use {@code 0} to use no limit
*/ */
protected ThreadPerChannelEventLoopGroup(int maxChannels) { protected ThreadPerChannelEventLoopGroup(int maxChannels) {
this(maxChannels, Executors.defaultThreadFactory()); this(maxChannels, Executors.defaultThreadFactory());
@ -84,7 +88,9 @@ public class ThreadPerChannelEventLoopGroup extends AbstractEventLoopGroup {
* *
* @param maxChannels the maximum number of channels to handle with this instance. Once you try to register * @param maxChannels the maximum number of channels to handle with this instance. Once you try to register
* a new {@link Channel} and the maximum is exceed it will throw an * a new {@link Channel} and the maximum is exceed it will throw an
* {@link ChannelException}. Use {@code 0} to use no limit * {@link ChannelException} on the {@link #register(Channel)} and
* {@link #register(Channel, ChannelPromise)} method.
* Use {@code 0} to use no limit
* @param threadFactory the {@link ThreadFactory} used to create new {@link Thread} instances that handle the * @param threadFactory the {@link ThreadFactory} used to create new {@link Thread} instances that handle the
* registered {@link Channel}s * registered {@link Channel}s
* @param args arguments which will passed to each {@link #newChild(Object...)} call. * @param args arguments which will passed to each {@link #newChild(Object...)} call.
@ -98,7 +104,9 @@ public class ThreadPerChannelEventLoopGroup extends AbstractEventLoopGroup {
* *
* @param maxChannels the maximum number of channels to handle with this instance. Once you try to register * @param maxChannels the maximum number of channels to handle with this instance. Once you try to register
* a new {@link Channel} and the maximum is exceed it will throw an * a new {@link Channel} and the maximum is exceed it will throw an
* {@link ChannelException}. Use {@code 0} to use no limit * {@link ChannelException} on the {@link #register(Channel)} and
* {@link #register(Channel, ChannelPromise)} method.
* Use {@code 0} to use no limit
* @param executor the {@link Executor} used to create new {@link Thread} instances that handle the * @param executor the {@link Executor} used to create new {@link Thread} instances that handle the
* registered {@link Channel}s * registered {@link Channel}s
* @param args arguments which will passed to each {@link #newChild(Object...)} call. * @param args arguments which will passed to each {@link #newChild(Object...)} call.
@ -126,34 +134,21 @@ public class ThreadPerChannelEventLoopGroup extends AbstractEventLoopGroup {
} }
/** /**
* Creates a new {@link EventLoop}. * Creates a new {@link EventLoop}. The default implementation creates a new {@link ThreadPerChannelEventLoop}.
*/ */
protected EventLoop newChild(@SuppressWarnings("UnusedParameters") Object... args) { protected EventLoop newChild(@SuppressWarnings("UnusedParameters") Object... args) throws Exception {
return new ThreadPerChannelEventLoop(this); return new ThreadPerChannelEventLoop(this);
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <E extends EventExecutor> Set<E> children() { public <E extends EventExecutor> Set<E> children() {
return Collections.unmodifiableSet((Set<E>) activeChildren); return (Set<E>) readOnlyActiveChildren;
} }
@Override @Override
public EventLoop next() { public EventLoop next() {
if (shuttingDown) { throw new UnsupportedOperationException();
throw new RejectedExecutionException("shutting down");
}
EventLoop loop = idleChildren.poll();
if (loop == null) {
if (maxChannels > 0 && activeChildren.size() >= maxChannels) {
throw tooManyChannels;
}
loop = newChild(childArgs);
loop.terminationFuture().addListener(childTerminationListener);
}
activeChildren.add(loop);
return loop;
} }
@Override @Override
@ -271,4 +266,47 @@ public class ThreadPerChannelEventLoopGroup extends AbstractEventLoopGroup {
} }
return isTerminated(); return isTerminated();
} }
@Override
public ChannelFuture register(Channel channel) {
if (channel == null) {
throw new NullPointerException("channel");
}
try {
EventLoop l = nextChild();
return l.register(channel, new DefaultChannelPromise(channel, l));
} catch (Throwable t) {
return new FailedChannelFuture(channel, GlobalEventExecutor.INSTANCE, t);
}
}
@Override
public ChannelFuture register(Channel channel, ChannelPromise promise) {
if (channel == null) {
throw new NullPointerException("channel");
}
try {
return nextChild().register(channel, promise);
} catch (Throwable t) {
promise.setFailure(t);
return promise;
}
}
private EventLoop nextChild() throws Exception {
if (shuttingDown) {
throw new RejectedExecutionException("shutting down");
}
EventLoop loop = idleChildren.poll();
if (loop == null) {
if (maxChannels > 0 && activeChildren.size() >= maxChannels) {
throw tooManyChannels;
}
loop = newChild(childArgs);
loop.terminationFuture().addListener(childTerminationListener);
}
activeChildren.add(loop);
return loop;
}
} }

View File

@ -1,172 +0,0 @@
/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GlobalEventExecutor;
import io.netty.util.internal.StringUtil;
import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;
/**
* A {@link Channel} that represents a non-existing {@link Channel} which could not be instantiated successfully.
*/
public final class VoidChannel extends AbstractChannel {
public static final VoidChannel INSTANCE = new VoidChannel();
private VoidChannel() {
super(null, new AbstractEventLoop(null) {
private final ChannelHandlerInvoker invoker =
new DefaultChannelHandlerInvoker(GlobalEventExecutor.INSTANCE);
@Override
@Deprecated
public void shutdown() {
GlobalEventExecutor.INSTANCE.shutdown();
}
@Override
public ChannelHandlerInvoker asInvoker() {
return invoker;
}
@Override
public boolean inEventLoop(Thread thread) {
return GlobalEventExecutor.INSTANCE.inEventLoop(thread);
}
@Override
public boolean isShuttingDown() {
return GlobalEventExecutor.INSTANCE.isShuttingDown();
}
@Override
public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
return GlobalEventExecutor.INSTANCE.shutdownGracefully(quietPeriod, timeout, unit);
}
@Override
public Future<?> terminationFuture() {
return GlobalEventExecutor.INSTANCE.terminationFuture();
}
@Override
public boolean isShutdown() {
return GlobalEventExecutor.INSTANCE.isShutdown();
}
@Override
public boolean isTerminated() {
return GlobalEventExecutor.INSTANCE.isTerminated();
}
@Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
return GlobalEventExecutor.INSTANCE.awaitTermination(timeout, unit);
}
@Override
public void execute(Runnable command) {
GlobalEventExecutor.INSTANCE.execute(command);
}
});
}
@Override
protected AbstractUnsafe newUnsafe() {
return new AbstractUnsafe() {
@Override
public void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
reject();
}
};
}
@Override
protected boolean isCompatible(EventLoop loop) {
return true;
}
@Override
protected SocketAddress localAddress0() {
return reject();
}
@Override
protected SocketAddress remoteAddress0() {
return reject();
}
@Override
protected void doBind(SocketAddress localAddress) throws Exception {
reject();
}
@Override
protected void doDisconnect() throws Exception {
reject();
}
@Override
protected void doClose() throws Exception {
reject();
}
@Override
protected void doBeginRead() throws Exception {
reject();
}
@Override
protected void doWrite(ChannelOutboundBuffer in) throws Exception {
reject();
}
@Override
public ChannelConfig config() {
return reject();
}
@Override
public boolean isOpen() {
return reject();
}
@Override
public boolean isActive() {
return reject();
}
@Override
public ChannelMetadata metadata() {
return reject();
}
@Override
public String toString() {
return StringUtil.simpleClassName(this);
}
private static <T> T reject() {
throw new UnsupportedOperationException(
StringUtil.simpleClassName(VoidChannel.class) +
" is only for the representation of a non-existing " +
StringUtil.simpleClassName(Channel.class) + '.');
}
}

View File

@ -54,7 +54,7 @@ public class EmbeddedChannel extends AbstractChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(false); private static final ChannelMetadata METADATA = new ChannelMetadata(false);
private final EmbeddedEventLoop loop; private final EmbeddedEventLoop loop = new EmbeddedEventLoop();
private final ChannelConfig config = new DefaultChannelConfig(this); private final ChannelConfig config = new DefaultChannelConfig(this);
private final Queue<Object> inboundMessages = new ArrayDeque<Object>(); private final Queue<Object> inboundMessages = new ArrayDeque<Object>();
private final Queue<Object> outboundMessages = new ArrayDeque<Object>(); private final Queue<Object> outboundMessages = new ArrayDeque<Object>();
@ -74,9 +74,7 @@ public class EmbeddedChannel extends AbstractChannel {
* @param handlers the @link ChannelHandler}s which will be add in the {@link ChannelPipeline} * @param handlers the @link ChannelHandler}s which will be add in the {@link ChannelPipeline}
*/ */
public EmbeddedChannel(ChannelHandler... handlers) { public EmbeddedChannel(ChannelHandler... handlers) {
super(null, new EmbeddedEventLoop()); super(null);
loop = (EmbeddedEventLoop) eventLoop();
if (handlers == null) { if (handlers == null) {
throw new NullPointerException("handlers"); throw new NullPointerException("handlers");
@ -91,7 +89,7 @@ public class EmbeddedChannel extends AbstractChannel {
} }
p.addLast(new LastInboundHandler()); p.addLast(new LastInboundHandler());
unsafe().register(newPromise()); loop.register(this);
} }
@Override @Override

View File

@ -16,6 +16,8 @@
package io.netty.channel.embedded; package io.netty.channel.embedded;
import io.netty.channel.AbstractEventLoop; import io.netty.channel.AbstractEventLoop;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelHandlerInvoker; import io.netty.channel.ChannelHandlerInvoker;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
@ -92,6 +94,17 @@ final class EmbeddedEventLoop extends AbstractEventLoop implements ChannelHandle
return false; return false;
} }
@Override
public ChannelFuture register(Channel channel) {
return register(channel, channel.newPromise());
}
@Override
public ChannelFuture register(Channel channel, ChannelPromise promise) {
channel.unsafe().register(this, promise);
return promise;
}
@Override @Override
public boolean inEventLoop() { public boolean inEventLoop() {
return true; return true;
@ -117,6 +130,11 @@ final class EmbeddedEventLoop extends AbstractEventLoop implements ChannelHandle
invokeChannelRegisteredNow(ctx); invokeChannelRegisteredNow(ctx);
} }
@Override
public void invokeChannelUnregistered(ChannelHandlerContext ctx) {
invokeChannelUnregisteredNow(ctx);
}
@Override @Override
public void invokeChannelActive(ChannelHandlerContext ctx) { public void invokeChannelActive(ChannelHandlerContext ctx) {
invokeChannelActiveNow(ctx); invokeChannelActiveNow(ctx);
@ -174,6 +192,11 @@ final class EmbeddedEventLoop extends AbstractEventLoop implements ChannelHandle
invokeCloseNow(ctx, promise); invokeCloseNow(ctx, promise);
} }
@Override
public void invokeDeregister(ChannelHandlerContext ctx, ChannelPromise promise) {
invokeDeregisterNow(ctx, promise);
}
@Override @Override
public void invokeRead(ChannelHandlerContext ctx) { public void invokeRead(ChannelHandlerContext ctx) {
invokeReadNow(ctx); invokeReadNow(ctx);

View File

@ -87,12 +87,12 @@ public class LocalChannel extends AbstractChannel {
private volatile boolean readInProgress; private volatile boolean readInProgress;
private volatile boolean registerInProgress; private volatile boolean registerInProgress;
public LocalChannel(EventLoop eventLoop) { public LocalChannel() {
super(null, eventLoop); super(null);
} }
LocalChannel(LocalServerChannel parent, EventLoop eventLoop, LocalChannel peer) { LocalChannel(LocalServerChannel parent, LocalChannel peer) {
super(parent, eventLoop); super(parent);
this.peer = peer; this.peer = peer;
localAddress = parent.localAddress(); localAddress = parent.localAddress();
remoteAddress = peer.localAddress(); remoteAddress = peer.localAddress();

View File

@ -20,7 +20,6 @@ import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.channel.DefaultChannelConfig; import io.netty.channel.DefaultChannelConfig;
import io.netty.channel.EventLoop; import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel; import io.netty.channel.ServerChannel;
import io.netty.channel.SingleThreadEventLoop; import io.netty.channel.SingleThreadEventLoop;
import io.netty.util.concurrent.SingleThreadEventExecutor; import io.netty.util.concurrent.SingleThreadEventExecutor;
@ -47,10 +46,6 @@ public class LocalServerChannel extends AbstractServerChannel {
private volatile LocalAddress localAddress; private volatile LocalAddress localAddress;
private volatile boolean acceptInProgress; private volatile boolean acceptInProgress;
public LocalServerChannel(EventLoop eventLoop, EventLoopGroup childGroup) {
super(eventLoop, childGroup);
}
@Override @Override
public ChannelConfig config() { public ChannelConfig config() {
return config; return config;
@ -136,7 +131,7 @@ public class LocalServerChannel extends AbstractServerChannel {
} }
LocalChannel serve(final LocalChannel peer) { LocalChannel serve(final LocalChannel peer) {
final LocalChannel child = new LocalChannel(this, childEventLoopGroup().next(), peer); final LocalChannel child = new LocalChannel(this, peer);
if (eventLoop().inEventLoop()) { if (eventLoop().inEventLoop()) {
serve0(child); serve0(child);
} else { } else {

View File

@ -22,7 +22,6 @@ import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoop;
import io.netty.channel.FileRegion; import io.netty.channel.FileRegion;
import io.netty.channel.RecvByteBufAllocator; import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.socket.ChannelInputShutdownEvent; import io.netty.channel.socket.ChannelInputShutdownEvent;
@ -44,8 +43,8 @@ public abstract class AbstractNioByteChannel extends AbstractNioChannel {
* @param parent the parent {@link Channel} by which this instance was created. May be {@code null} * @param parent the parent {@link Channel} by which this instance was created. May be {@code null}
* @param ch the underlying {@link SelectableChannel} on which it operates * @param ch the underlying {@link SelectableChannel} on which it operates
*/ */
protected AbstractNioByteChannel(Channel parent, EventLoop eventLoop, SelectableChannel ch) { protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {
super(parent, eventLoop, ch, SelectionKey.OP_READ); super(parent, ch, SelectionKey.OP_READ);
} }
@Override @Override

View File

@ -65,8 +65,8 @@ public abstract class AbstractNioChannel extends AbstractChannel {
* @param ch the underlying {@link SelectableChannel} on which it operates * @param ch the underlying {@link SelectableChannel} on which it operates
* @param readInterestOp the ops to set to receive data from the {@link SelectableChannel} * @param readInterestOp the ops to set to receive data from the {@link SelectableChannel}
*/ */
protected AbstractNioChannel(Channel parent, EventLoop eventLoop, SelectableChannel ch, int readInterestOp) { protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent, eventLoop); super(parent);
this.ch = ch; this.ch = ch;
this.readInterestOp = readInterestOp; this.readInterestOp = readInterestOp;
try { try {

View File

@ -19,7 +19,6 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelConfig; import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoop;
import io.netty.channel.ServerChannel; import io.netty.channel.ServerChannel;
import java.io.IOException; import java.io.IOException;
@ -33,9 +32,11 @@ import java.util.List;
*/ */
public abstract class AbstractNioMessageChannel extends AbstractNioChannel { public abstract class AbstractNioMessageChannel extends AbstractNioChannel {
protected AbstractNioMessageChannel( /**
Channel parent, EventLoop eventLoop, SelectableChannel ch, int readInterestOp) { * @see {@link AbstractNioChannel#AbstractNioChannel(Channel, SelectableChannel, int)}
super(parent, eventLoop, ch, readInterestOp); */
protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent, ch, readInterestOp);
} }
@Override @Override
@ -169,5 +170,4 @@ public abstract class AbstractNioMessageChannel extends AbstractNioChannel {
* @return {@code true} if and only if the message has been written * @return {@code true} if and only if the message has been written
*/ */
protected abstract boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception; protected abstract boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception;
} }

View File

@ -1,39 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.nio;
import io.netty.channel.Channel;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel;
import java.nio.channels.SelectableChannel;
public abstract class AbstractNioMessageServerChannel extends AbstractNioMessageChannel implements ServerChannel {
private final EventLoopGroup childGroup;
protected AbstractNioMessageServerChannel(
Channel parent, EventLoop eventLoop, EventLoopGroup childGroup, SelectableChannel ch, int readInterestOp) {
super(parent, eventLoop, ch, readInterestOp);
this.childGroup = childGroup;
}
@Override
public EventLoopGroup childEventLoopGroup() {
return childGroup;
}
}

View File

@ -22,7 +22,6 @@ import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoop;
import io.netty.channel.FileRegion; import io.netty.channel.FileRegion;
import io.netty.channel.socket.ChannelInputShutdownEvent; import io.netty.channel.socket.ChannelInputShutdownEvent;
import io.netty.util.internal.StringUtil; import io.netty.util.internal.StringUtil;
@ -37,8 +36,11 @@ public abstract class AbstractOioByteChannel extends AbstractOioChannel {
private volatile boolean inputShutdown; private volatile boolean inputShutdown;
private static final ChannelMetadata METADATA = new ChannelMetadata(false); private static final ChannelMetadata METADATA = new ChannelMetadata(false);
protected AbstractOioByteChannel(Channel parent, EventLoop eventLoop) { /**
super(parent, eventLoop); * @see AbstractOioByteChannel#AbstractOioByteChannel(Channel)
*/
protected AbstractOioByteChannel(Channel parent) {
super(parent);
} }
protected boolean isInputShutdown() { protected boolean isInputShutdown() {

View File

@ -46,8 +46,11 @@ public abstract class AbstractOioChannel extends AbstractChannel {
} }
}; };
protected AbstractOioChannel(Channel parent, EventLoop eventLoop) { /**
super(parent, eventLoop); * @see AbstractChannel#AbstractChannel(Channel)
*/
protected AbstractOioChannel(Channel parent) {
super(parent);
} }
@Override @Override

View File

@ -18,8 +18,6 @@ package io.netty.channel.oio;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelConfig; import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoop;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -31,8 +29,8 @@ public abstract class AbstractOioMessageChannel extends AbstractOioChannel {
private final List<Object> readBuf = new ArrayList<Object>(); private final List<Object> readBuf = new ArrayList<Object>();
protected AbstractOioMessageChannel(Channel parent, EventLoop eventLoop) { protected AbstractOioMessageChannel(Channel parent) {
super(parent, eventLoop); super(parent);
} }
@Override @Override

View File

@ -1,36 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.oio;
import io.netty.channel.Channel;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel;
public abstract class AbstractOioMessageServerChannel extends AbstractOioMessageChannel implements ServerChannel {
private final EventLoopGroup childGroup;
protected AbstractOioMessageServerChannel(Channel parent, EventLoop eventLoop, EventLoopGroup childGroup) {
super(parent, eventLoop);
this.childGroup = childGroup;
}
@Override
public EventLoopGroup childEventLoopGroup() {
return childGroup;
}
}

View File

@ -17,7 +17,6 @@ package io.netty.channel.oio;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.EventLoop;
import io.netty.channel.FileRegion; import io.netty.channel.FileRegion;
import java.io.IOException; import java.io.IOException;
@ -57,8 +56,8 @@ public abstract class OioByteStreamChannel extends AbstractOioByteChannel {
* @param parent the parent {@link Channel} which was used to create this instance. This can be null if the * @param parent the parent {@link Channel} which was used to create this instance. This can be null if the
* {@link} has no parent as it was created by your self. * {@link} has no parent as it was created by your self.
*/ */
protected OioByteStreamChannel(Channel parent, EventLoop eventLoop) { protected OioByteStreamChannel(Channel parent) {
super(parent, eventLoop); super(parent);
} }
/** /**

View File

@ -25,7 +25,6 @@ import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoop;
import io.netty.channel.RecvByteBufAllocator; import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.nio.AbstractNioMessageChannel; import io.netty.channel.nio.AbstractNioMessageChannel;
import io.netty.channel.socket.DatagramChannelConfig; import io.netty.channel.socket.DatagramChannelConfig;
@ -106,40 +105,27 @@ public final class NioDatagramChannel
/** /**
* Create a new instance which will use the Operation Systems default {@link InternetProtocolFamily}. * Create a new instance which will use the Operation Systems default {@link InternetProtocolFamily}.
*/ */
public NioDatagramChannel(EventLoop eventLoop) { public NioDatagramChannel() {
this(eventLoop, newSocket(DEFAULT_SELECTOR_PROVIDER)); 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(EventLoop eventLoop, SelectorProvider provider) {
this(eventLoop, newSocket(provider));
} }
/** /**
* Create a new instance using the given {@link InternetProtocolFamily}. If {@code null} is used it will depend * Create a new instance using the given {@link InternetProtocolFamily}. If {@code null} is used it will depend
* on the Operation Systems default which will be chosen. * on the Operation Systems default which will be chosen.
*/ */
public NioDatagramChannel(EventLoop eventLoop, InternetProtocolFamily ipFamily) { public NioDatagramChannel(InternetProtocolFamily ipFamily) {
this(eventLoop, newSocket(DEFAULT_SELECTOR_PROVIDER, ipFamily)); this(DEFAULT_SELECTOR_PROVIDER, ipFamily);
} }
/** public NioDatagramChannel(SelectorProvider provider, InternetProtocolFamily ipFamily) {
* Create a new instance using the given {@link SelectorProvider} and {@link InternetProtocolFamily}. this(newSocket(provider, ipFamily));
* If {@link InternetProtocolFamily} is {@code null} it will depend on the Operation Systems default
* which will be chosen.
*/
public NioDatagramChannel(EventLoop eventLoop, SelectorProvider provider, InternetProtocolFamily ipFamily) {
this(eventLoop, newSocket(provider, ipFamily));
} }
/** /**
* Create a new instance from the given {@link DatagramChannel}. * Create a new instance from the given {@link DatagramChannel}.
*/ */
public NioDatagramChannel(EventLoop eventLoop, DatagramChannel socket) { public NioDatagramChannel(DatagramChannel socket) {
super(null, eventLoop, socket, SelectionKey.OP_READ); super(null, socket, SelectionKey.OP_READ);
config = new NioDatagramChannelConfig(this, socket); config = new NioDatagramChannelConfig(this, socket);
} }

View File

@ -18,9 +18,7 @@ package io.netty.channel.socket.nio;
import io.netty.channel.ChannelException; import io.netty.channel.ChannelException;
import io.netty.channel.ChannelMetadata; import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.EventLoop; import io.netty.channel.nio.AbstractNioMessageChannel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.AbstractNioMessageServerChannel;
import io.netty.channel.socket.DefaultServerSocketChannelConfig; import io.netty.channel.socket.DefaultServerSocketChannelConfig;
import io.netty.channel.socket.ServerSocketChannelConfig; import io.netty.channel.socket.ServerSocketChannelConfig;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
@ -40,7 +38,7 @@ import java.util.List;
* A {@link io.netty.channel.socket.ServerSocketChannel} implementation which uses * A {@link io.netty.channel.socket.ServerSocketChannel} implementation which uses
* NIO selector based implementation to accept new connections. * NIO selector based implementation to accept new connections.
*/ */
public class NioServerSocketChannel extends AbstractNioMessageServerChannel public class NioServerSocketChannel extends AbstractNioMessageChannel
implements io.netty.channel.socket.ServerSocketChannel { implements io.netty.channel.socket.ServerSocketChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(false); private static final ChannelMetadata METADATA = new ChannelMetadata(false);
@ -68,22 +66,12 @@ public class NioServerSocketChannel extends AbstractNioMessageServerChannel
/** /**
* Create a new instance * Create a new instance
*/ */
public NioServerSocketChannel(EventLoop eventLoop, EventLoopGroup childGroup) { public NioServerSocketChannel() {
this(eventLoop, childGroup, newSocket(DEFAULT_SELECTOR_PROVIDER)); this(DEFAULT_SELECTOR_PROVIDER);
} }
/** public NioServerSocketChannel(SelectorProvider provider) {
* Create a new instance using the given {@link SelectorProvider}. super(null, newSocket(provider), SelectionKey.OP_ACCEPT);
*/
public NioServerSocketChannel(EventLoop eventLoop, EventLoopGroup childGroup, SelectorProvider provider) {
this(eventLoop, childGroup, newSocket(provider));
}
/**
* Create a new instance using the given {@link ServerSocketChannel}.
*/
public NioServerSocketChannel(EventLoop eventLoop, EventLoopGroup childGroup, ServerSocketChannel channel) {
super(null, eventLoop, childGroup, channel, SelectionKey.OP_ACCEPT);
config = new NioServerSocketChannelConfig(this, javaChannel().socket()); config = new NioServerSocketChannelConfig(this, javaChannel().socket());
} }
@ -138,7 +126,7 @@ public class NioServerSocketChannel extends AbstractNioMessageServerChannel
try { try {
if (ch != null) { if (ch != null) {
buf.add(new NioSocketChannel(this, childEventLoopGroup().next(), ch)); buf.add(new NioSocketChannel(this, ch));
return 1; return 1;
} }
} catch (Throwable t) { } catch (Throwable t) {

View File

@ -66,32 +66,31 @@ public class NioSocketChannel extends AbstractNioByteChannel implements io.netty
/** /**
* Create a new instance * Create a new instance
*/ */
public NioSocketChannel(EventLoop eventLoop) { public NioSocketChannel() {
this(eventLoop, newSocket(DEFAULT_SELECTOR_PROVIDER)); this(DEFAULT_SELECTOR_PROVIDER);
} }
/** /**
* Create a new instance using the given {@link SelectorProvider}. * Create a new instance using the given {@link SelectorProvider}.
*/ */
public NioSocketChannel(EventLoop eventLoop, SelectorProvider provider) { public NioSocketChannel(SelectorProvider provider) {
this(eventLoop, newSocket(provider)); this(newSocket(provider));
} }
/** /**
* Create a new instance using the given {@link SocketChannel}. * Create a new instance using the given {@link SocketChannel}.
*/ */
public NioSocketChannel(EventLoop eventLoop, SocketChannel socket) { public NioSocketChannel(SocketChannel socket) {
this(null, eventLoop, socket); this(null, socket);
} }
/** /**
* Create a new instance * Create a new instance
* *
* @param parent the {@link Channel} which created this instance or {@code null} if it was created by the user * @param parent the {@link Channel} which created this instance or {@code null} if it was created by the user
* @param socket the {@link SocketChannel} which will be used * @param socket the {@link SocketChannel} which will be used
*/ */
public NioSocketChannel(Channel parent, EventLoop eventLoop, SocketChannel socket) { public NioSocketChannel(Channel parent, SocketChannel socket) {
super(parent, eventLoop, socket); super(parent, socket);
config = new NioSocketChannelConfig(this, socket.socket()); config = new NioSocketChannelConfig(this, socket.socket());
} }

View File

@ -25,7 +25,6 @@ import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoop;
import io.netty.channel.RecvByteBufAllocator; import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.oio.AbstractOioMessageChannel; import io.netty.channel.oio.AbstractOioMessageChannel;
import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.DatagramChannel;
@ -56,7 +55,8 @@ import java.util.Locale;
* @see AddressedEnvelope * @see AddressedEnvelope
* @see DatagramPacket * @see DatagramPacket
*/ */
public final class OioDatagramChannel extends AbstractOioMessageChannel implements DatagramChannel { public class OioDatagramChannel extends AbstractOioMessageChannel
implements DatagramChannel {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(OioDatagramChannel.class); private static final InternalLogger logger = InternalLoggerFactory.getInstance(OioDatagramChannel.class);
@ -79,8 +79,8 @@ public final class OioDatagramChannel extends AbstractOioMessageChannel implemen
/** /**
* Create a new instance with an new {@link MulticastSocket}. * Create a new instance with an new {@link MulticastSocket}.
*/ */
public OioDatagramChannel(EventLoop eventLoop) { public OioDatagramChannel() {
this(eventLoop, newSocket()); this(newSocket());
} }
/** /**
@ -88,8 +88,8 @@ public final class OioDatagramChannel extends AbstractOioMessageChannel implemen
* *
* @param socket the {@link MulticastSocket} which is used by this instance * @param socket the {@link MulticastSocket} which is used by this instance
*/ */
public OioDatagramChannel(EventLoop eventLoop, MulticastSocket socket) { public OioDatagramChannel(MulticastSocket socket) {
super(null, eventLoop); super(null);
boolean success = false; boolean success = false;
try { try {

View File

@ -18,9 +18,7 @@ package io.netty.channel.socket.oio;
import io.netty.channel.ChannelException; import io.netty.channel.ChannelException;
import io.netty.channel.ChannelMetadata; import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.EventLoop; import io.netty.channel.oio.AbstractOioMessageChannel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.oio.AbstractOioMessageServerChannel;
import io.netty.channel.socket.ServerSocketChannel; import io.netty.channel.socket.ServerSocketChannel;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
@ -40,7 +38,8 @@ import java.util.concurrent.locks.ReentrantLock;
* *
* This implementation use Old-Blocking-IO. * This implementation use Old-Blocking-IO.
*/ */
public class OioServerSocketChannel extends AbstractOioMessageServerChannel implements ServerSocketChannel { public class OioServerSocketChannel extends AbstractOioMessageChannel
implements ServerSocketChannel {
private static final InternalLogger logger = private static final InternalLogger logger =
InternalLoggerFactory.getInstance(OioServerSocketChannel.class); InternalLoggerFactory.getInstance(OioServerSocketChannel.class);
@ -62,8 +61,8 @@ public class OioServerSocketChannel extends AbstractOioMessageServerChannel impl
/** /**
* Create a new instance with an new {@link Socket} * Create a new instance with an new {@link Socket}
*/ */
public OioServerSocketChannel(EventLoop eventLoop, EventLoopGroup childGroup) { public OioServerSocketChannel() {
this(eventLoop, childGroup, newServerSocket()); this(newServerSocket());
} }
/** /**
@ -71,8 +70,8 @@ public class OioServerSocketChannel extends AbstractOioMessageServerChannel impl
* *
* @param socket the {@link ServerSocket} which is used by this instance * @param socket the {@link ServerSocket} which is used by this instance
*/ */
public OioServerSocketChannel(EventLoop eventLoop, EventLoopGroup childGroup, ServerSocket socket) { public OioServerSocketChannel(ServerSocket socket) {
super(null, eventLoop, childGroup); super(null);
if (socket == null) { if (socket == null) {
throw new NullPointerException("socket"); throw new NullPointerException("socket");
} }
@ -155,7 +154,7 @@ public class OioServerSocketChannel extends AbstractOioMessageServerChannel impl
Socket s = socket.accept(); Socket s = socket.accept();
try { try {
if (s != null) { if (s != null) {
buf.add(new OioSocketChannel(this, childEventLoopGroup().next(), s)); buf.add(new OioSocketChannel(this, s));
return 1; return 1;
} }
} catch (Throwable t) { } catch (Throwable t) {

View File

@ -49,8 +49,8 @@ public class OioSocketChannel extends OioByteStreamChannel
/** /**
* Create a new instance with an new {@link Socket} * Create a new instance with an new {@link Socket}
*/ */
public OioSocketChannel(EventLoop eventLoop) { public OioSocketChannel() {
this(eventLoop, new Socket()); this(new Socket());
} }
/** /**
@ -58,8 +58,8 @@ public class OioSocketChannel extends OioByteStreamChannel
* *
* @param socket the {@link Socket} which is used by this instance * @param socket the {@link Socket} which is used by this instance
*/ */
public OioSocketChannel(EventLoop eventLoop, Socket socket) { public OioSocketChannel(Socket socket) {
this(null, eventLoop, socket); this(null, socket);
} }
/** /**
@ -69,8 +69,8 @@ public class OioSocketChannel extends OioByteStreamChannel
* {@link} has no parent as it was created by your self. * {@link} has no parent as it was created by your self.
* @param socket the {@link Socket} which is used by this instance * @param socket the {@link Socket} which is used by this instance
*/ */
public OioSocketChannel(Channel parent, EventLoop eventLoop, Socket socket) { public OioSocketChannel(Channel parent, Socket socket) {
super(parent, eventLoop); super(parent);
this.socket = socket; this.socket = socket;
config = new DefaultOioSocketChannelConfig(this, socket); config = new DefaultOioSocketChannelConfig(this, socket);

View File

@ -137,7 +137,7 @@ public class DefaultChannelPipelineTest {
@Test @Test
public void testRemoveChannelHandler() { public void testRemoveChannelHandler() {
ChannelPipeline pipeline = new LocalChannel(group.next()).pipeline(); ChannelPipeline pipeline = new LocalChannel().pipeline();
ChannelHandler handler1 = newHandler(); ChannelHandler handler1 = newHandler();
ChannelHandler handler2 = newHandler(); ChannelHandler handler2 = newHandler();
@ -160,7 +160,7 @@ public class DefaultChannelPipelineTest {
@Test @Test
public void testReplaceChannelHandler() { public void testReplaceChannelHandler() {
ChannelPipeline pipeline = new LocalChannel(group.next()).pipeline(); ChannelPipeline pipeline = new LocalChannel().pipeline();
ChannelHandler handler1 = newHandler(); ChannelHandler handler1 = newHandler();
pipeline.addLast("handler1", handler1); pipeline.addLast("handler1", handler1);
@ -185,7 +185,7 @@ public class DefaultChannelPipelineTest {
@Test @Test
public void testChannelHandlerContextNavigation() { public void testChannelHandlerContextNavigation() {
ChannelPipeline pipeline = new LocalChannel(group.next()).pipeline(); ChannelPipeline pipeline = new LocalChannel().pipeline();
final int HANDLER_ARRAY_LEN = 5; final int HANDLER_ARRAY_LEN = 5;
ChannelHandler[] firstHandlers = newHandlers(HANDLER_ARRAY_LEN); ChannelHandler[] firstHandlers = newHandlers(HANDLER_ARRAY_LEN);
@ -200,12 +200,11 @@ public class DefaultChannelPipelineTest {
@Test @Test
public void testFireChannelRegistered() throws Exception { public void testFireChannelRegistered() throws Exception {
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
Channel ch = new LocalChannel(group.next()); ChannelPipeline pipeline = new LocalChannel().pipeline();
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ChannelInitializer<Channel>() { pipeline.addLast(new ChannelInitializer<Channel>() {
@Override @Override
protected void initChannel(Channel ch) throws Exception { protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new ChannelHandlerAdapter() { ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
@Override @Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception { public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
latch.countDown(); latch.countDown();
@ -213,13 +212,13 @@ public class DefaultChannelPipelineTest {
}); });
} }
}); });
ch.unsafe().register(ch.newPromise()); group.register(pipeline.channel());
assertTrue(latch.await(2, TimeUnit.SECONDS)); assertTrue(latch.await(2, TimeUnit.SECONDS));
} }
@Test @Test
public void testPipelineOperation() { public void testPipelineOperation() {
ChannelPipeline pipeline = new LocalChannel(group.next()).pipeline(); ChannelPipeline pipeline = new LocalChannel().pipeline();
final int handlerNum = 5; final int handlerNum = 5;
ChannelHandler[] handlers1 = newHandlers(handlerNum); ChannelHandler[] handlers1 = newHandlers(handlerNum);
@ -247,7 +246,7 @@ public class DefaultChannelPipelineTest {
@Test @Test
public void testChannelHandlerContextOrder() { public void testChannelHandlerContextOrder() {
ChannelPipeline pipeline = new LocalChannel(group.next()).pipeline(); ChannelPipeline pipeline = new LocalChannel().pipeline();
pipeline.addFirst("1", newHandler()); pipeline.addFirst("1", newHandler());
pipeline.addLast("10", newHandler()); pipeline.addLast("10", newHandler());
@ -444,7 +443,8 @@ public class DefaultChannelPipelineTest {
// Tests for https://github.com/netty/netty/issues/2349 // Tests for https://github.com/netty/netty/issues/2349
@Test @Test
public void testCancelBind() throws Exception { public void testCancelBind() throws Exception {
ChannelPipeline pipeline = new LocalChannel(group.next()).pipeline(); ChannelPipeline pipeline = new LocalChannel().pipeline();
group.register(pipeline.channel());
ChannelPromise promise = pipeline.channel().newPromise(); ChannelPromise promise = pipeline.channel().newPromise();
assertTrue(promise.cancel(false)); assertTrue(promise.cancel(false));
@ -454,7 +454,8 @@ public class DefaultChannelPipelineTest {
@Test @Test
public void testCancelConnect() throws Exception { public void testCancelConnect() throws Exception {
ChannelPipeline pipeline = new LocalChannel(group.next()).pipeline(); ChannelPipeline pipeline = new LocalChannel().pipeline();
group.register(pipeline.channel());
ChannelPromise promise = pipeline.channel().newPromise(); ChannelPromise promise = pipeline.channel().newPromise();
assertTrue(promise.cancel(false)); assertTrue(promise.cancel(false));
@ -464,7 +465,8 @@ public class DefaultChannelPipelineTest {
@Test @Test
public void testCancelDisconnect() throws Exception { public void testCancelDisconnect() throws Exception {
ChannelPipeline pipeline = new LocalChannel(group.next()).pipeline(); ChannelPipeline pipeline = new LocalChannel().pipeline();
group.register(pipeline.channel());
ChannelPromise promise = pipeline.channel().newPromise(); ChannelPromise promise = pipeline.channel().newPromise();
assertTrue(promise.cancel(false)); assertTrue(promise.cancel(false));
@ -474,7 +476,8 @@ public class DefaultChannelPipelineTest {
@Test @Test
public void testCancelClose() throws Exception { public void testCancelClose() throws Exception {
ChannelPipeline pipeline = new LocalChannel(group.next()).pipeline(); ChannelPipeline pipeline = new LocalChannel().pipeline();
group.register(pipeline.channel());
ChannelPromise promise = pipeline.channel().newPromise(); ChannelPromise promise = pipeline.channel().newPromise();
assertTrue(promise.cancel(false)); assertTrue(promise.cancel(false));
@ -482,9 +485,21 @@ public class DefaultChannelPipelineTest {
assertTrue(future.isCancelled()); assertTrue(future.isCancelled());
} }
@Test
public void testCancelDeregister() throws Exception {
ChannelPipeline pipeline = new LocalChannel().pipeline();
group.register(pipeline.channel());
ChannelPromise promise = pipeline.channel().newPromise();
assertTrue(promise.cancel(false));
ChannelFuture future = pipeline.deregister(promise);
assertTrue(future.isCancelled());
}
@Test @Test
public void testCancelWrite() throws Exception { public void testCancelWrite() throws Exception {
ChannelPipeline pipeline = new LocalChannel(group.next()).pipeline(); ChannelPipeline pipeline = new LocalChannel().pipeline();
group.register(pipeline.channel());
ChannelPromise promise = pipeline.channel().newPromise(); ChannelPromise promise = pipeline.channel().newPromise();
assertTrue(promise.cancel(false)); assertTrue(promise.cancel(false));
@ -497,7 +512,8 @@ public class DefaultChannelPipelineTest {
@Test @Test
public void testCancelWriteAndFlush() throws Exception { public void testCancelWriteAndFlush() throws Exception {
ChannelPipeline pipeline = new LocalChannel(group.next()).pipeline(); ChannelPipeline pipeline = new LocalChannel().pipeline();
group.register(pipeline.channel());
ChannelPromise promise = pipeline.channel().newPromise(); ChannelPromise promise = pipeline.channel().newPromise();
assertTrue(promise.cancel(false)); assertTrue(promise.cancel(false));

View File

@ -22,8 +22,8 @@ import java.util.EnumSet;
final class LoggingHandler implements ChannelHandler { final class LoggingHandler implements ChannelHandler {
enum Event { enum Event {
WRITE, FLUSH, BIND, CONNECT, DISCONNECT, CLOSE, READ, WRITABILITY, HANDLER_ADDED, WRITE, FLUSH, BIND, CONNECT, DISCONNECT, CLOSE, DEREGISTER, READ, WRITABILITY, HANDLER_ADDED,
HANDLER_REMOVED, EXCEPTION, READ_COMPLETE, REGISTERED, ACTIVE, INACTIVE, USER HANDLER_REMOVED, EXCEPTION, READ_COMPLETE, REGISTERED, UNREGISTERED, ACTIVE, INACTIVE, USER
} }
private StringBuilder log = new StringBuilder(); private StringBuilder log = new StringBuilder();
@ -68,6 +68,12 @@ final class LoggingHandler implements ChannelHandler {
ctx.close(promise); ctx.close(promise);
} }
@Override
public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
log(Event.DEREGISTER);
ctx.deregister(promise);
}
@Override @Override
public void read(ChannelHandlerContext ctx) throws Exception { public void read(ChannelHandlerContext ctx) throws Exception {
log(Event.READ); log(Event.READ);
@ -101,6 +107,12 @@ final class LoggingHandler implements ChannelHandler {
ctx.fireChannelRegistered(); ctx.fireChannelRegistered();
} }
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
log(Event.UNREGISTERED);
ctx.fireChannelUnregistered();
}
@Override @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception { public void channelActive(ChannelHandlerContext ctx) throws Exception {
log(Event.ACTIVE); log(Event.ACTIVE);

View File

@ -339,13 +339,11 @@ public class SingleThreadEventLoopTest {
} }
try { try {
Channel channel = new LocalChannel(loopA); ChannelFuture f = loopA.register(new LocalChannel());
ChannelPromise f = channel.newPromise();
channel.unsafe().register(f);
f.awaitUninterruptibly(); f.awaitUninterruptibly();
assertFalse(f.isSuccess()); assertFalse(f.isSuccess());
assertThat(f.cause(), is(instanceOf(RejectedExecutionException.class))); assertThat(f.cause(), is(instanceOf(RejectedExecutionException.class)));
assertFalse(channel.isOpen()); assertFalse(f.channel().isOpen());
} finally { } finally {
for (Appender<ILoggingEvent> a: appenders) { for (Appender<ILoggingEvent> a: appenders) {
root.addAppender(a); root.addAppender(a);
@ -358,7 +356,7 @@ public class SingleThreadEventLoopTest {
public void testRegistrationAfterShutdown2() throws Exception { public void testRegistrationAfterShutdown2() throws Exception {
loopA.shutdown(); loopA.shutdown();
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
Channel ch = new LocalChannel(loopA); Channel ch = new LocalChannel();
ChannelPromise promise = ch.newPromise(); ChannelPromise promise = ch.newPromise();
promise.addListener(new ChannelFutureListener() { promise.addListener(new ChannelFutureListener() {
@Override @Override
@ -377,10 +375,10 @@ public class SingleThreadEventLoopTest {
} }
try { try {
ch.unsafe().register(promise); ChannelFuture f = loopA.register(ch, promise);
promise.awaitUninterruptibly(); f.awaitUninterruptibly();
assertFalse(promise.isSuccess()); assertFalse(f.isSuccess());
assertThat(promise.cause(), is(instanceOf(RejectedExecutionException.class))); assertThat(f.cause(), is(instanceOf(RejectedExecutionException.class)));
// Ensure the listener was notified. // Ensure the listener was notified.
assertFalse(latch.await(1, TimeUnit.SECONDS)); assertFalse(latch.await(1, TimeUnit.SECONDS));

View File

@ -82,7 +82,7 @@ public class ThreadPerChannelEventLoopGroupTest {
ChannelGroup channelGroup = new DefaultChannelGroup(testExecutor); ChannelGroup channelGroup = new DefaultChannelGroup(testExecutor);
while (taskCount-- > 0) { while (taskCount-- > 0) {
Channel channel = new EmbeddedChannel(NOOP_HANDLER); Channel channel = new EmbeddedChannel(NOOP_HANDLER);
channel.unsafe().register(new DefaultChannelPromise(channel, testExecutor)); loopGroup.register(channel, new DefaultChannelPromise(channel, testExecutor));
channelGroup.add(channel); channelGroup.add(channel);
} }
channelGroup.close().sync(); channelGroup.close().sync();

View File

@ -89,7 +89,7 @@ public class LocalTransportThreadModelTest {
ThreadNameAuditor h2 = new ThreadNameAuditor(); ThreadNameAuditor h2 = new ThreadNameAuditor();
ThreadNameAuditor h3 = new ThreadNameAuditor(true); ThreadNameAuditor h3 = new ThreadNameAuditor(true);
Channel ch = new LocalChannel(l.next()); Channel ch = new LocalChannel();
// With no EventExecutor specified, h1 will be always invoked by EventLoop 'l'. // With no EventExecutor specified, h1 will be always invoked by EventLoop 'l'.
ch.pipeline().addLast(h1); ch.pipeline().addLast(h1);
// h2 will be always invoked by EventExecutor 'e1'. // h2 will be always invoked by EventExecutor 'e1'.
@ -97,9 +97,7 @@ public class LocalTransportThreadModelTest {
// h3 will be always invoked by EventExecutor 'e2'. // h3 will be always invoked by EventExecutor 'e2'.
ch.pipeline().addLast(e2, h3); ch.pipeline().addLast(e2, h3);
ChannelPromise promise = ch.newPromise(); l.register(ch).sync().channel().connect(localAddr).sync();
ch.unsafe().register(promise);
promise.sync().channel().connect(localAddr).sync();
// Fire inbound events from all possible starting points. // Fire inbound events from all possible starting points.
ch.pipeline().fireChannelRead("1"); ch.pipeline().fireChannelRead("1");
@ -242,7 +240,7 @@ public class LocalTransportThreadModelTest {
final MessageForwarder2 h5 = new MessageForwarder2(); final MessageForwarder2 h5 = new MessageForwarder2();
final MessageDiscarder h6 = new MessageDiscarder(); final MessageDiscarder h6 = new MessageDiscarder();
final Channel ch = new LocalChannel(l.next()); final Channel ch = new LocalChannel();
// inbound: int -> byte[4] -> int -> int -> byte[4] -> int -> /dev/null // inbound: int -> byte[4] -> int -> int -> byte[4] -> int -> /dev/null
// outbound: int -> int -> byte[4] -> int -> int -> byte[4] -> /dev/null // outbound: int -> int -> byte[4] -> int -> int -> byte[4] -> /dev/null
@ -253,9 +251,7 @@ public class LocalTransportThreadModelTest {
.addLast(e4, h5) .addLast(e4, h5)
.addLast(e5, h6); .addLast(e5, h6);
ChannelPromise promise = ch.newPromise(); l.register(ch).sync().channel().connect(localAddr).sync();
ch.unsafe().register(promise);
promise.sync().channel().connect(localAddr).sync();
final int ROUNDS = 1024; final int ROUNDS = 1024;
final int ELEMS_PER_ROUNDS = 8192; final int ELEMS_PER_ROUNDS = 8192;

View File

@ -130,7 +130,7 @@ public class LocalTransportThreadModelTest3 {
final EventForwarder h5 = new EventForwarder(); final EventForwarder h5 = new EventForwarder();
final EventRecorder h6 = new EventRecorder(events, inbound); final EventRecorder h6 = new EventRecorder(events, inbound);
final Channel ch = new LocalChannel(l.next()); final Channel ch = new LocalChannel();
if (!inbound) { if (!inbound) {
ch.config().setAutoRead(false); ch.config().setAutoRead(false);
} }
@ -141,9 +141,7 @@ public class LocalTransportThreadModelTest3 {
.addLast(e1, h5) .addLast(e1, h5)
.addLast(e1, "recorder", h6); .addLast(e1, "recorder", h6);
ChannelPromise promise = ch.newPromise(); l.register(ch).sync().channel().connect(localAddr).sync();
ch.unsafe().register(promise);
promise.sync().channel().connect(localAddr).sync();
final LinkedList<EventType> expectedEvents = events(inbound, 8192); final LinkedList<EventType> expectedEvents = events(inbound, 8192);