Synchronized between 4.1 and master
Motivation: 4 and 5 were diverged long time ago and we recently reverted some of the early commits in master. We must make sure 4.1 and master are not very different now. Modification: Fix found differences Result: 4.1 and master got closer.
This commit is contained in:
parent
d2614cfc01
commit
7fa861ab70
@ -36,6 +36,7 @@ import java.util.NoSuchElementException;
|
|||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default {@link ChannelPipeline} implementation. It is usually created
|
* The default {@link ChannelPipeline} implementation. It is usually created
|
||||||
@ -49,10 +50,21 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
private static final WeakHashMap<Class<?>, String>[] nameCaches =
|
private static final WeakHashMap<Class<?>, String>[] nameCaches =
|
||||||
new WeakHashMap[Runtime.getRuntime().availableProcessors()];
|
new WeakHashMap[Runtime.getRuntime().availableProcessors()];
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
private static final AtomicReferenceFieldUpdater<DefaultChannelPipeline, Map> childInvokersUpdater;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
for (int i = 0; i < nameCaches.length; i ++) {
|
for (int i = 0; i < nameCaches.length; i ++) {
|
||||||
nameCaches[i] = new WeakHashMap<Class<?>, String>();
|
nameCaches[i] = new WeakHashMap<Class<?>, String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
AtomicReferenceFieldUpdater<DefaultChannelPipeline, Map> updater;
|
||||||
|
updater = PlatformDependent.newAtomicReferenceFieldUpdater(DefaultChannelPipeline.class, "childInvokers");
|
||||||
|
if (updater == null) {
|
||||||
|
updater = AtomicReferenceFieldUpdater.newUpdater(DefaultChannelPipeline.class, Map.class, "childInvokers");
|
||||||
|
}
|
||||||
|
childInvokersUpdater = updater;
|
||||||
}
|
}
|
||||||
|
|
||||||
final AbstractChannel channel;
|
final AbstractChannel channel;
|
||||||
@ -63,10 +75,15 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
private final Map<String, DefaultChannelHandlerContext> name2ctx =
|
private final Map<String, DefaultChannelHandlerContext> name2ctx =
|
||||||
new HashMap<String, DefaultChannelHandlerContext>(4);
|
new HashMap<String, DefaultChannelHandlerContext>(4);
|
||||||
|
|
||||||
final Map<EventExecutorGroup, ChannelHandlerInvoker> childInvokers =
|
/**
|
||||||
new IdentityHashMap<EventExecutorGroup, ChannelHandlerInvoker>();
|
* Updated by {@link #childInvokersUpdater}.
|
||||||
|
*
|
||||||
|
* @see #findInvoker(EventExecutorGroup)
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
|
private volatile Map<EventExecutorGroup, ChannelHandlerInvoker> childInvokers;
|
||||||
|
|
||||||
public DefaultChannelPipeline(AbstractChannel channel) {
|
DefaultChannelPipeline(AbstractChannel channel) {
|
||||||
if (channel == null) {
|
if (channel == null) {
|
||||||
throw new NullPointerException("channel");
|
throw new NullPointerException("channel");
|
||||||
}
|
}
|
||||||
@ -101,13 +118,8 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
public ChannelPipeline addFirst(ChannelHandlerInvoker invoker, final String name, ChannelHandler handler) {
|
public ChannelPipeline addFirst(ChannelHandlerInvoker invoker, final String name, ChannelHandler handler) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
checkDuplicateName(name);
|
checkDuplicateName(name);
|
||||||
|
addFirst0(name, new DefaultChannelHandlerContext(this, invoker, name, handler));
|
||||||
DefaultChannelHandlerContext newCtx =
|
|
||||||
new DefaultChannelHandlerContext(this, invoker, name, handler);
|
|
||||||
|
|
||||||
addFirst0(name, newCtx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,13 +151,8 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
public ChannelPipeline addLast(ChannelHandlerInvoker invoker, final String name, ChannelHandler handler) {
|
public ChannelPipeline addLast(ChannelHandlerInvoker invoker, final String name, ChannelHandler handler) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
checkDuplicateName(name);
|
checkDuplicateName(name);
|
||||||
|
addLast0(name, new DefaultChannelHandlerContext(this, invoker, name, handler));
|
||||||
DefaultChannelHandlerContext newCtx =
|
|
||||||
new DefaultChannelHandlerContext(this, invoker, name, handler);
|
|
||||||
|
|
||||||
addLast0(name, newCtx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,13 +185,8 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
ChannelHandlerInvoker invoker, String baseName, final String name, ChannelHandler handler) {
|
ChannelHandlerInvoker invoker, String baseName, final String name, ChannelHandler handler) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
DefaultChannelHandlerContext ctx = getContextOrDie(baseName);
|
DefaultChannelHandlerContext ctx = getContextOrDie(baseName);
|
||||||
|
|
||||||
checkDuplicateName(name);
|
checkDuplicateName(name);
|
||||||
|
addBefore0(name, ctx, new DefaultChannelHandlerContext(this, invoker, name, handler));
|
||||||
DefaultChannelHandlerContext newCtx =
|
|
||||||
new DefaultChannelHandlerContext(this, invoker, name, handler);
|
|
||||||
|
|
||||||
addBefore0(name, ctx, newCtx);
|
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -217,15 +219,9 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
ChannelHandlerInvoker invoker, String baseName, final String name, ChannelHandler handler) {
|
ChannelHandlerInvoker invoker, String baseName, final String name, ChannelHandler handler) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
DefaultChannelHandlerContext ctx = getContextOrDie(baseName);
|
DefaultChannelHandlerContext ctx = getContextOrDie(baseName);
|
||||||
|
|
||||||
checkDuplicateName(name);
|
checkDuplicateName(name);
|
||||||
|
addAfter0(name, ctx, new DefaultChannelHandlerContext(this, invoker, name, handler));
|
||||||
DefaultChannelHandlerContext newCtx =
|
|
||||||
new DefaultChannelHandlerContext(this, invoker, name, handler);
|
|
||||||
|
|
||||||
addAfter0(name, ctx, newCtx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,17 +304,29 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pin one of the child executors once and remember it so that the same child executor
|
// Lazily initialize the data structure that maps an EventExecutorGroup to a ChannelHandlerInvoker.
|
||||||
// is used to fire events for the same channel.
|
Map<EventExecutorGroup, ChannelHandlerInvoker> childInvokers = this.childInvokers;
|
||||||
ChannelHandlerInvoker invoker = childInvokers.get(group);
|
if (childInvokers == null) {
|
||||||
if (invoker == null) {
|
childInvokers = new IdentityHashMap<EventExecutorGroup, ChannelHandlerInvoker>();
|
||||||
EventExecutor executor = group.next();
|
if (!childInvokersUpdater.compareAndSet(this, null, childInvokers)) {
|
||||||
if (executor instanceof EventLoop) {
|
childInvokers = this.childInvokers;
|
||||||
invoker = ((EventLoop) executor).asInvoker();
|
}
|
||||||
} else {
|
}
|
||||||
invoker = new DefaultChannelHandlerInvoker(executor);
|
|
||||||
|
// Pick one of the child executors and remember its invoker
|
||||||
|
// so that the same invoker is used to fire events for the same channel.
|
||||||
|
ChannelHandlerInvoker invoker;
|
||||||
|
synchronized (childInvokers) {
|
||||||
|
invoker = childInvokers.get(group);
|
||||||
|
if (invoker == null) {
|
||||||
|
EventExecutor executor = group.next();
|
||||||
|
if (executor instanceof EventLoop) {
|
||||||
|
invoker = ((EventLoop) executor).asInvoker();
|
||||||
|
} else {
|
||||||
|
invoker = new DefaultChannelHandlerInvoker(executor);
|
||||||
|
}
|
||||||
|
childInvokers.put(group, invoker);
|
||||||
}
|
}
|
||||||
childInvokers.put(group, invoker);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return invoker;
|
return invoker;
|
||||||
@ -550,7 +558,6 @@ 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);
|
||||||
@ -936,7 +943,7 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture deregister(ChannelPromise promise) {
|
public ChannelFuture deregister(ChannelPromise promise) {
|
||||||
return tail.close(promise);
|
return tail.deregister(promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1043,9 +1050,9 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
static final class HeadHandler extends ChannelHandlerAdapter {
|
static final class HeadHandler extends ChannelHandlerAdapter {
|
||||||
|
|
||||||
protected final Unsafe unsafe;
|
private final Unsafe unsafe;
|
||||||
|
|
||||||
protected HeadHandler(Unsafe unsafe) {
|
HeadHandler(Unsafe unsafe) {
|
||||||
this.unsafe = unsafe;
|
this.unsafe = unsafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,14 +109,27 @@ public final class NioDatagramChannel
|
|||||||
this(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(SelectorProvider provider) {
|
||||||
|
this(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(InternetProtocolFamily ipFamily) {
|
public NioDatagramChannel(InternetProtocolFamily ipFamily) {
|
||||||
this(DEFAULT_SELECTOR_PROVIDER, ipFamily);
|
this(newSocket(DEFAULT_SELECTOR_PROVIDER, ipFamily));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance using the given {@link SelectorProvider} and {@link InternetProtocolFamily}.
|
||||||
|
* If {@link InternetProtocolFamily} is {@code null} it will depend on the Operation Systems default
|
||||||
|
* which will be chosen.
|
||||||
|
*/
|
||||||
public NioDatagramChannel(SelectorProvider provider, InternetProtocolFamily ipFamily) {
|
public NioDatagramChannel(SelectorProvider provider, InternetProtocolFamily ipFamily) {
|
||||||
this(newSocket(provider, ipFamily));
|
this(newSocket(provider, ipFamily));
|
||||||
}
|
}
|
||||||
|
@ -67,11 +67,21 @@ public class NioServerSocketChannel extends AbstractNioMessageChannel
|
|||||||
* Create a new instance
|
* Create a new instance
|
||||||
*/
|
*/
|
||||||
public NioServerSocketChannel() {
|
public NioServerSocketChannel() {
|
||||||
this(DEFAULT_SELECTOR_PROVIDER);
|
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance using the given {@link SelectorProvider}.
|
||||||
|
*/
|
||||||
public NioServerSocketChannel(SelectorProvider provider) {
|
public NioServerSocketChannel(SelectorProvider provider) {
|
||||||
super(null, newSocket(provider), SelectionKey.OP_ACCEPT);
|
this(newSocket(provider));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance using the given {@link ServerSocketChannel}.
|
||||||
|
*/
|
||||||
|
public NioServerSocketChannel(ServerSocketChannel channel) {
|
||||||
|
super(null, channel, SelectionKey.OP_ACCEPT);
|
||||||
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
|
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,8 +23,6 @@ import io.netty.buffer.Unpooled;
|
|||||||
import io.netty.channel.local.LocalChannel;
|
import io.netty.channel.local.LocalChannel;
|
||||||
import io.netty.channel.local.LocalServerChannel;
|
import io.netty.channel.local.LocalServerChannel;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
class BaseChannelTest {
|
class BaseChannelTest {
|
||||||
@ -66,18 +64,6 @@ class BaseChannelTest {
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object createTestBuf(String string) throws UnsupportedEncodingException {
|
|
||||||
byte[] buf = string.getBytes("US-ASCII");
|
|
||||||
return createTestBuf(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Object createTestBuf(byte[] buf) {
|
|
||||||
ByteBuf ret = createTestBuf(buf.length);
|
|
||||||
ret.clear();
|
|
||||||
ret.writeBytes(buf);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void assertLog(String expected) {
|
void assertLog(String expected) {
|
||||||
String actual = loggingHandler.getLog();
|
String actual = loggingHandler.getLog();
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
@ -90,4 +76,5 @@ class BaseChannelTest {
|
|||||||
void setInterest(LoggingHandler.Event... events) {
|
void setInterest(LoggingHandler.Event... events) {
|
||||||
loggingHandler.setInterest(events);
|
loggingHandler.setInterest(events);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user