Remove Channel.id completely / Use 64-bit hashCode internally to reduce the chance of collision in compareTo()

This commit is contained in:
Trustin Lee 2013-07-09 14:49:06 +09:00
parent 9c1b31d20a
commit 7396f9f2b2
29 changed files with 129 additions and 176 deletions

View File

@ -40,7 +40,7 @@ public class RxtxChannel extends OioByteStreamChannel {
private SerialPort serialPort;
public RxtxChannel() {
super(null, null);
super(null);
config = new DefaultRxtxChannelConfig(this);
}

View File

@ -86,7 +86,7 @@ public class NioSctpChannel extends AbstractNioMessageChannel implements io.nett
* Create a new instance using {@link SctpChannel}
*/
public NioSctpChannel(SctpChannel sctpChannel) {
this(null, null, sctpChannel);
this(null, sctpChannel);
}
/**
@ -94,12 +94,10 @@ public class NioSctpChannel extends AbstractNioMessageChannel implements io.nett
*
* @param parent the {@link Channel} which is the parent of this {@link NioSctpChannel}
* or {@code null}.
* @param id the id to use for this instance or {@code null} if a new once should be
* generated
* @param sctpChannel the underlying {@link SctpChannel}
*/
public NioSctpChannel(Channel parent, Integer id, SctpChannel sctpChannel) {
super(parent, id, sctpChannel, SelectionKey.OP_READ);
public NioSctpChannel(Channel parent, SctpChannel sctpChannel) {
super(parent, sctpChannel, SelectionKey.OP_READ);
try {
sctpChannel.configureBlocking(false);
config = new DefaultSctpChannelConfig(this, sctpChannel);

View File

@ -62,7 +62,7 @@ public class NioSctpServerChannel extends AbstractNioMessageChannel
* Create a new instance
*/
public NioSctpServerChannel() {
super(null, null, newSocket(), SelectionKey.OP_ACCEPT);
super(null, newSocket(), SelectionKey.OP_ACCEPT);
config = new DefaultSctpServerChannelConfig(this, javaChannel());
}
@ -139,7 +139,7 @@ public class NioSctpServerChannel extends AbstractNioMessageChannel
if (ch == null) {
return 0;
}
buf.add(new NioSctpChannel(this, null, ch));
buf.add(new NioSctpChannel(this, ch));
return 1;
}

View File

@ -96,7 +96,7 @@ public class OioSctpChannel extends AbstractOioMessageChannel
* @param ch the {@link SctpChannel} which is used by this instance
*/
public OioSctpChannel(SctpChannel ch) {
this(null, null, ch);
this(null, ch);
}
/**
@ -104,11 +104,10 @@ public class OioSctpChannel extends AbstractOioMessageChannel
*
* @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.
* @param id the id which should be used for this instance or {@code null} if a new one should be generated
* @param ch the {@link SctpChannel} which is used by this instance
*/
public OioSctpChannel(Channel parent, Integer id, SctpChannel ch) {
super(parent, id);
public OioSctpChannel(Channel parent, SctpChannel ch) {
super(parent);
this.ch = ch;
boolean success = false;
try {

View File

@ -80,17 +80,7 @@ public class OioSctpServerChannel extends AbstractOioMessageChannel
* @param sch the {@link SctpServerChannel} which is used by this instance
*/
public OioSctpServerChannel(SctpServerChannel sch) {
this(null, sch);
}
/**
* Create a new instance from the given {@link SctpServerChannel}
*
* @param id the id which should be used for this instance or {@code null} if a new one should be generated
* @param sch the {@link SctpServerChannel} which is used by this instance
*/
public OioSctpServerChannel(Integer id, SctpServerChannel sch) {
super(null, id);
super(null);
if (sch == null) {
throw new NullPointerException("sctp server channel");
}
@ -206,7 +196,7 @@ public class OioSctpServerChannel extends AbstractOioMessageChannel
if (key.isAcceptable()) {
s = sch.accept();
if (s != null) {
buf.add(new OioSctpChannel(this, null, s));
buf.add(new OioSctpChannel(this, s));
acceptedChannels ++;
}
}

View File

@ -34,16 +34,15 @@ import static java.nio.channels.SelectionKey.*;
/**
* Common base for Netty Byte/Message UDT Stream/Datagram acceptors.
*/
public abstract class NioUdtAcceptorChannel extends AbstractNioMessageChannel
implements UdtServerChannel {
public abstract class NioUdtAcceptorChannel extends AbstractNioMessageChannel implements UdtServerChannel {
protected static final InternalLogger logger = InternalLoggerFactory
.getInstance(NioUdtAcceptorChannel.class);
protected static final InternalLogger logger =
InternalLoggerFactory.getInstance(NioUdtAcceptorChannel.class);
private final UdtServerChannelConfig config;
protected NioUdtAcceptorChannel(final ServerSocketChannelUDT channelUDT) {
super(null, channelUDT.socketUDT().id(), channelUDT, OP_ACCEPT);
super(null, channelUDT, OP_ACCEPT);
try {
channelUDT.configureBlocking(false);
config = new DefaultUdtServerChannelConfig(this, channelUDT, true);

View File

@ -37,7 +37,7 @@ public class NioUdtByteAcceptorChannel extends NioUdtAcceptorChannel {
if (channelUDT == null) {
return 0;
} else {
buf.add(new NioUdtByteConnectorChannel(this, channelUDT.socketUDT().id(), channelUDT));
buf.add(new NioUdtByteConnectorChannel(this, channelUDT));
return 1;
}
}

View File

@ -37,11 +37,10 @@ import static java.nio.channels.SelectionKey.*;
/**
* Byte Channel Connector for UDT Streams.
*/
public class NioUdtByteConnectorChannel extends AbstractNioByteChannel
implements UdtChannel {
public class NioUdtByteConnectorChannel extends AbstractNioByteChannel implements UdtChannel {
private static final InternalLogger logger = InternalLoggerFactory
.getInstance(NioUdtByteConnectorChannel.class);
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(NioUdtByteConnectorChannel.class);
private static final ChannelMetadata METADATA = new ChannelMetadata(false);
@ -51,9 +50,8 @@ public class NioUdtByteConnectorChannel extends AbstractNioByteChannel
this(TypeUDT.STREAM);
}
public NioUdtByteConnectorChannel(final Channel parent, final Integer id,
final SocketChannelUDT channelUDT) {
super(parent, id, channelUDT);
public NioUdtByteConnectorChannel(final Channel parent, final SocketChannelUDT channelUDT) {
super(parent, channelUDT);
try {
channelUDT.configureBlocking(false);
switch (channelUDT.socketUDT().status()) {
@ -78,7 +76,7 @@ public class NioUdtByteConnectorChannel extends AbstractNioByteChannel
}
public NioUdtByteConnectorChannel(final SocketChannelUDT channelUDT) {
this(null, channelUDT.socketUDT().id(), channelUDT);
this(null, channelUDT);
}
public NioUdtByteConnectorChannel(final TypeUDT type) {

View File

@ -37,7 +37,7 @@ public class NioUdtMessageAcceptorChannel extends NioUdtAcceptorChannel {
if (channelUDT == null) {
return 0;
} else {
buf.add(new NioUdtMessageConnectorChannel(this, channelUDT.socketUDT().id(), channelUDT));
buf.add(new NioUdtMessageConnectorChannel(this, channelUDT));
return 1;
}
}

View File

@ -41,11 +41,10 @@ import static java.nio.channels.SelectionKey.*;
* <p>
* Note: send/receive must use {@link UdtMessage} in the pipeline
*/
public class NioUdtMessageConnectorChannel extends AbstractNioMessageChannel
implements UdtChannel {
public class NioUdtMessageConnectorChannel extends AbstractNioMessageChannel implements UdtChannel {
private static final InternalLogger logger = InternalLoggerFactory
.getInstance(NioUdtMessageConnectorChannel.class);
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(NioUdtMessageConnectorChannel.class);
private static final ChannelMetadata METADATA = new ChannelMetadata(false);
@ -55,9 +54,8 @@ public class NioUdtMessageConnectorChannel extends AbstractNioMessageChannel
this(TypeUDT.DATAGRAM);
}
public NioUdtMessageConnectorChannel(final Channel parent,
final Integer id, final SocketChannelUDT channelUDT) {
super(parent, id, channelUDT, OP_READ);
public NioUdtMessageConnectorChannel(final Channel parent, final SocketChannelUDT channelUDT) {
super(parent, channelUDT, OP_READ);
try {
channelUDT.configureBlocking(false);
switch (channelUDT.socketUDT().status()) {
@ -82,7 +80,7 @@ public class NioUdtMessageConnectorChannel extends AbstractNioMessageChannel
}
public NioUdtMessageConnectorChannel(final SocketChannelUDT channelUDT) {
this(null, channelUDT.socketUDT().id(), channelUDT);
this(null, channelUDT);
}
public NioUdtMessageConnectorChannel(final TypeUDT type) {

View File

@ -39,23 +39,8 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractChannel.class);
/**
* Generates a negative unique integer ID. This method generates only
* negative integers to avoid conflicts with user-specified IDs where only
* non-negative integers are allowed.
*/
private static Integer allocateId() {
int idVal = ThreadLocalRandom.current().nextInt();
if (idVal > 0) {
idVal = -idVal;
} else if (idVal == 0) {
idVal = -1;
}
return idVal;
}
private final Channel parent;
private final Integer id;
private final long hashCode = ThreadLocalRandom.current().nextLong();
private final Unsafe unsafe;
private final DefaultChannelPipeline pipeline;
private final ChannelOutboundBuffer outboundBuffer = new ChannelOutboundBuffer(this);
@ -80,24 +65,11 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
/**
* Creates a new instance.
*
* @param id
* the unique non-negative integer ID of this channel.
* Specify {@code null} to auto-generate a unique negative integer
* ID.
* @param parent
* the parent of this channel. {@code null} if there's no parent.
*/
protected AbstractChannel(Channel parent, Integer id) {
if (id == null) {
id = allocateId();
} else {
if (id.intValue() < 0) {
throw new IllegalArgumentException("id: " + id + " (expected: >= 0)");
}
}
protected AbstractChannel(Channel parent) {
this.parent = parent;
this.id = id;
unsafe = newUnsafe();
pipeline = new DefaultChannelPipeline(this);
}
@ -300,7 +272,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
*/
@Override
public final int hashCode() {
return id;
return (int) hashCode;
}
/**
@ -314,10 +286,25 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
@Override
public final int compareTo(Channel o) {
if (o instanceof AbstractChannel) {
return id.compareTo(((AbstractChannel) o).id);
if (this == o) {
return 0;
}
return id.compareTo(Integer.valueOf(o.hashCode()));
long ret = hashCode - o.hashCode();
if (ret > 0) {
return 1;
}
if (ret < 0) {
return -1;
}
ret = System.identityHashCode(this) - System.identityHashCode(o);
if (ret != 0) {
return (int) ret;
}
// Jackpot! - different objects with same hashes
throw new Error();
}
/**
@ -345,11 +332,11 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
srcAddr = remoteAddr;
dstAddr = localAddr;
}
strVal = String.format("[id: 0x%08x, %s %s %s]", id, srcAddr, active? "=>" : ":>", dstAddr);
strVal = String.format("[id: 0x%08x, %s %s %s]", (int) hashCode, srcAddr, active? "=>" : ":>", dstAddr);
} else if (localAddr != null) {
strVal = String.format("[id: 0x%08x, %s]", id, localAddr);
strVal = String.format("[id: 0x%08x, %s]", (int) hashCode, localAddr);
} else {
strVal = String.format("[id: 0x%08x]", id);
strVal = String.format("[id: 0x%08x]", (int) hashCode);
}
strValActive = active;

View File

@ -36,8 +36,8 @@ public abstract class AbstractServerChannel extends AbstractChannel implements S
/**
* Creates a new instance.
*/
protected AbstractServerChannel(Integer id) {
super(null, id);
protected AbstractServerChannel() {
super(null);
}
@Override

View File

@ -47,6 +47,42 @@ import java.util.NoSuchElementException;
* </ul>
* </p>
*
* <h3>Consuming the messages from a {@link MessageList} efficiently yet safely</h3>
* <p>
* The following example shows how to iterate over the list which contains {@code ReferenceCounted} messages safely
* (i.e. without leaking them) while consuming the messages.
* </p>
* <pre>
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageList}&lt;Object&gt; msgs) {
* final int size = msgs.size();
* final Object[] in = msgs.array();
* boolean success = false;
* try {
* for (int i = 0; i < size; i ++) {
* Object m = in[i];
*
* // Handle the message.
* doSomethingWithMessage(m);
*
* // Release the handled message.
* {@link ReferenceCountUtil#release(Object) ReferenceCountUtil.release(m)};
*
* // To prevent {@link #releaseAllAndRecycle()} from releasing the message again,
* // replace the message with a dummy object.
* in[i] = MessageList.NONE;
* }
*
* success = true;
* } finally {
* if (success) {
* {@link #recycle() msgs.recycle()};
* } else {
* {@link #releaseAllAndRecycle() msgs.releaseAllAndRecycle()};
* }
* }
* }
* </pre>
*
* @param <T> the type of the contained messages
*/
public final class MessageList<T> implements Iterable<T> {
@ -240,7 +276,13 @@ public final class MessageList<T> implements Iterable<T> {
if (value == null) {
throw new NullPointerException("value");
}
elements[index] = value;
if (byteBufsOnly && !(value instanceof ByteBuf)) {
byteBufsOnly = false;
}
return this;
}

View File

@ -61,7 +61,7 @@ public class EmbeddedChannel extends AbstractChannel {
* @param handlers the @link ChannelHandler}s which will be add in the {@link ChannelPipeline}
*/
public EmbeddedChannel(ChannelHandler... handlers) {
super(null, null);
super(null);
if (handlers == null) {
throw new NullPointerException("handlers");

View File

@ -83,15 +83,11 @@ public class LocalChannel extends AbstractChannel {
private volatile boolean readInProgress;
public LocalChannel() {
this(null);
}
public LocalChannel(Integer id) {
super(null, id);
super(null);
}
LocalChannel(LocalServerChannel parent, LocalChannel peer) {
super(parent, null);
super(parent);
this.peer = peer;
localAddress = parent.localAddress();
remoteAddress = peer.localAddress();

View File

@ -47,22 +47,6 @@ public class LocalServerChannel extends AbstractServerChannel {
private volatile LocalAddress localAddress;
private volatile boolean acceptInProgress;
/**
* Creates a new instance
*/
public LocalServerChannel() {
this(null);
}
/**
* Create a new instance
*
* @param id the id to use or {@code null} if a new id should be generated
*/
public LocalServerChannel(Integer id) {
super(id);
}
@Override
public ChannelConfig config() {
return config;

View File

@ -40,12 +40,10 @@ public abstract class AbstractNioByteChannel extends AbstractNioChannel {
* Create a new instance
*
* @param parent the parent {@link Channel} by which this instance was created. May be {@code null}
* @param id the id of this instance or {@code null} if one should be generated
* @param ch the underlying {@link SelectableChannel} on which it operates
*/
protected AbstractNioByteChannel(
Channel parent, Integer id, SelectableChannel ch) {
super(parent, id, ch, SelectionKey.OP_READ);
protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {
super(parent, ch, SelectionKey.OP_READ);
}
@Override

View File

@ -63,13 +63,11 @@ public abstract class AbstractNioChannel extends AbstractChannel {
* Create a new instance
*
* @param parent the parent {@link Channel} by which this instance was created. May be {@code null}
* @param id the id of this instance or {@code null} if one should be generated
* @param ch the underlying {@link SelectableChannel} on which it operates
* @param readInterestOp the ops to set to receive data from the {@link SelectableChannel}
*/
protected AbstractNioChannel(
Channel parent, Integer id, SelectableChannel ch, int readInterestOp) {
super(parent, id);
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent);
this.ch = ch;
this.readInterestOp = readInterestOp;
try {

View File

@ -30,11 +30,10 @@ import java.nio.channels.SelectionKey;
public abstract class AbstractNioMessageChannel extends AbstractNioChannel {
/**
* @see {@link AbstractNioChannel#AbstractNioChannel(Channel, Integer, SelectableChannel, int)}
* @see {@link AbstractNioChannel#AbstractNioChannel(Channel, SelectableChannel, int)}
*/
protected AbstractNioMessageChannel(
Channel parent, Integer id, SelectableChannel ch, int readInterestOp) {
super(parent, id, ch, readInterestOp);
protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent, ch, readInterestOp);
}
@Override

View File

@ -36,10 +36,10 @@ public abstract class AbstractOioByteChannel extends AbstractOioChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(false);
/**
* @see AbstractOioByteChannel#AbstractOioByteChannel(Channel, Integer)
* @see AbstractOioByteChannel#AbstractOioByteChannel(Channel)
*/
protected AbstractOioByteChannel(Channel parent, Integer id) {
super(parent, id);
protected AbstractOioByteChannel(Channel parent) {
super(parent);
}
protected boolean isInputShutdown() {

View File

@ -42,10 +42,10 @@ public abstract class AbstractOioChannel extends AbstractChannel {
};
/**
* @see AbstractChannel#AbstractChannel(Channel, Integer)
* @see AbstractChannel#AbstractChannel(Channel)
*/
protected AbstractOioChannel(Channel parent, Integer id) {
super(parent, id);
protected AbstractOioChannel(Channel parent) {
super(parent);
}
@Override

View File

@ -26,8 +26,8 @@ import java.io.IOException;
*/
public abstract class AbstractOioMessageChannel extends AbstractOioChannel {
protected AbstractOioMessageChannel(Channel parent, Integer id) {
super(parent, id);
protected AbstractOioMessageChannel(Channel parent) {
super(parent);
}
@Override

View File

@ -55,10 +55,9 @@ 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
* {@link} has no parent as it was created by your self.
* @param id the id which should be used for this instance or {@code null} if a new one should be generated
*/
protected OioByteStreamChannel(Channel parent, Integer id) {
super(parent, id);
protected OioByteStreamChannel(Channel parent) {
super(parent);
}
/**

View File

@ -110,17 +110,7 @@ public final class NioDatagramChannel
* Create a new instance from the given {@link DatagramChannel}.
*/
public NioDatagramChannel(DatagramChannel socket) {
this(null, socket);
}
/**
* Create a new instance from the given {@link DatagramChannel}.
*
* @param id the id to use for this instance or {@code null} if a new one should be generated.
* @param socket the {@link DatagramChannel} which will be used
*/
public NioDatagramChannel(Integer id, DatagramChannel socket) {
super(null, id, socket, SelectionKey.OP_READ);
super(null, socket, SelectionKey.OP_READ);
config = new NioDatagramChannelConfig(this, socket);
}

View File

@ -57,7 +57,7 @@ public class NioServerSocketChannel extends AbstractNioMessageChannel
* Create a new instance
*/
public NioServerSocketChannel() {
super(null, null, newSocket(), SelectionKey.OP_ACCEPT);
super(null, newSocket(), SelectionKey.OP_ACCEPT);
config = new DefaultServerSocketChannelConfig(this, javaChannel().socket());
}
@ -112,7 +112,7 @@ public class NioServerSocketChannel extends AbstractNioMessageChannel
try {
if (ch != null) {
buf.add(new NioSocketChannel(this, null, ch));
buf.add(new NioSocketChannel(this, ch));
return 1;
}
} catch (Throwable t) {

View File

@ -88,18 +88,17 @@ public class NioSocketChannel extends AbstractNioByteChannel implements io.netty
* Create a new instance using the given {@link SocketChannel}.
*/
public NioSocketChannel(SocketChannel socket) {
this(null, null, socket);
this(null, socket);
}
/**
* Create a new instance
*
* @param parent the {@link Channel} which created this instance or {@code null} if it was created by the user
* @param id the id to use for this instance or {@code null} if a new one should be generated
* @param socket the {@link SocketChannel} which will be used
*/
public NioSocketChannel(Channel parent, Integer id, SocketChannel socket) {
super(parent, id, socket);
public NioSocketChannel(Channel parent, SocketChannel socket) {
super(parent, socket);
try {
socket.configureBlocking(false);
} catch (IOException e) {

View File

@ -88,17 +88,7 @@ public class OioDatagramChannel extends AbstractOioMessageChannel
* @param socket the {@link MulticastSocket} which is used by this instance
*/
public OioDatagramChannel(MulticastSocket socket) {
this(null, socket);
}
/**
* Create a new instance from the given {@link MulticastSocket}.
*
* @param id the id which should be used for this instance or {@code null} if a new one should be generated
* @param socket the {@link MulticastSocket} which is used by this instance
*/
public OioDatagramChannel(Integer id, MulticastSocket socket) {
super(null, id);
super(null);
boolean success = false;
try {

View File

@ -70,17 +70,7 @@ public class OioServerSocketChannel extends AbstractOioMessageChannel
* @param socket the {@link ServerSocket} which is used by this instance
*/
public OioServerSocketChannel(ServerSocket socket) {
this(null, socket);
}
/**
* Create a new instance from the given {@link ServerSocket}
*
* @param id the id which should be used for this instance or {@code null} if a new one should be generated
* @param socket the {@link ServerSocket} which is used by this instance
*/
public OioServerSocketChannel(Integer id, ServerSocket socket) {
super(null, id);
super(null);
if (socket == null) {
throw new NullPointerException("socket");
}
@ -163,7 +153,7 @@ public class OioServerSocketChannel extends AbstractOioMessageChannel
Socket s = socket.accept();
try {
if (s != null) {
buf.add(new OioSocketChannel(this, null, s));
buf.add(new OioSocketChannel(this, s));
return 1;
}
} catch (Throwable t) {

View File

@ -59,7 +59,7 @@ public class OioSocketChannel extends OioByteStreamChannel
* @param socket the {@link Socket} which is used by this instance
*/
public OioSocketChannel(Socket socket) {
this(null, null, socket);
this(null, socket);
}
/**
@ -67,11 +67,10 @@ public class OioSocketChannel extends OioByteStreamChannel
*
* @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.
* @param id the id which should be used for this instance or {@code null} if a new one should be generated
* @param socket the {@link Socket} which is used by this instance
*/
public OioSocketChannel(Channel parent, Integer id, Socket socket) {
super(parent, id);
public OioSocketChannel(Channel parent, Socket socket) {
super(parent);
this.socket = socket;
config = new DefaultOioSocketChannelConfig(this, socket);