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.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||
|
||||
/**
|
||||
* 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 =
|
||||
new WeakHashMap[Runtime.getRuntime().availableProcessors()];
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final AtomicReferenceFieldUpdater<DefaultChannelPipeline, Map> childInvokersUpdater;
|
||||
|
||||
static {
|
||||
for (int i = 0; i < nameCaches.length; i ++) {
|
||||
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;
|
||||
@ -63,10 +75,15 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
||||
private final Map<String, DefaultChannelHandlerContext> name2ctx =
|
||||
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) {
|
||||
throw new NullPointerException("channel");
|
||||
}
|
||||
@ -101,13 +118,8 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
||||
public ChannelPipeline addFirst(ChannelHandlerInvoker invoker, final String name, ChannelHandler handler) {
|
||||
synchronized (this) {
|
||||
checkDuplicateName(name);
|
||||
|
||||
DefaultChannelHandlerContext newCtx =
|
||||
new DefaultChannelHandlerContext(this, invoker, name, handler);
|
||||
|
||||
addFirst0(name, newCtx);
|
||||
addFirst0(name, new DefaultChannelHandlerContext(this, invoker, name, handler));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -139,13 +151,8 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
||||
public ChannelPipeline addLast(ChannelHandlerInvoker invoker, final String name, ChannelHandler handler) {
|
||||
synchronized (this) {
|
||||
checkDuplicateName(name);
|
||||
|
||||
DefaultChannelHandlerContext newCtx =
|
||||
new DefaultChannelHandlerContext(this, invoker, name, handler);
|
||||
|
||||
addLast0(name, newCtx);
|
||||
addLast0(name, new DefaultChannelHandlerContext(this, invoker, name, handler));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -178,13 +185,8 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
||||
ChannelHandlerInvoker invoker, String baseName, final String name, ChannelHandler handler) {
|
||||
synchronized (this) {
|
||||
DefaultChannelHandlerContext ctx = getContextOrDie(baseName);
|
||||
|
||||
checkDuplicateName(name);
|
||||
|
||||
DefaultChannelHandlerContext newCtx =
|
||||
new DefaultChannelHandlerContext(this, invoker, name, handler);
|
||||
|
||||
addBefore0(name, ctx, newCtx);
|
||||
addBefore0(name, ctx, new DefaultChannelHandlerContext(this, invoker, name, handler));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -217,15 +219,9 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
||||
ChannelHandlerInvoker invoker, String baseName, final String name, ChannelHandler handler) {
|
||||
synchronized (this) {
|
||||
DefaultChannelHandlerContext ctx = getContextOrDie(baseName);
|
||||
|
||||
checkDuplicateName(name);
|
||||
|
||||
DefaultChannelHandlerContext newCtx =
|
||||
new DefaultChannelHandlerContext(this, invoker, name, handler);
|
||||
|
||||
addAfter0(name, ctx, newCtx);
|
||||
addAfter0(name, ctx, new DefaultChannelHandlerContext(this, invoker, name, handler));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -308,17 +304,29 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Pin one of the child executors once and remember it so that the same child executor
|
||||
// is used to fire events for the same channel.
|
||||
ChannelHandlerInvoker invoker = childInvokers.get(group);
|
||||
if (invoker == null) {
|
||||
EventExecutor executor = group.next();
|
||||
if (executor instanceof EventLoop) {
|
||||
invoker = ((EventLoop) executor).asInvoker();
|
||||
} else {
|
||||
invoker = new DefaultChannelHandlerInvoker(executor);
|
||||
// Lazily initialize the data structure that maps an EventExecutorGroup to a ChannelHandlerInvoker.
|
||||
Map<EventExecutorGroup, ChannelHandlerInvoker> childInvokers = this.childInvokers;
|
||||
if (childInvokers == null) {
|
||||
childInvokers = new IdentityHashMap<EventExecutorGroup, ChannelHandlerInvoker>();
|
||||
if (!childInvokersUpdater.compareAndSet(this, null, childInvokers)) {
|
||||
childInvokers = this.childInvokers;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
@ -550,7 +558,6 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
||||
try {
|
||||
ctx.handler().handlerAdded(ctx);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
boolean removed = false;
|
||||
try {
|
||||
remove(ctx);
|
||||
@ -936,7 +943,7 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
||||
|
||||
@Override
|
||||
public ChannelFuture deregister(ChannelPromise promise) {
|
||||
return tail.close(promise);
|
||||
return tail.deregister(promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1043,9 +1050,9 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
||||
|
||||
static final class HeadHandler extends ChannelHandlerAdapter {
|
||||
|
||||
protected final Unsafe unsafe;
|
||||
private final Unsafe unsafe;
|
||||
|
||||
protected HeadHandler(Unsafe unsafe) {
|
||||
HeadHandler(Unsafe unsafe) {
|
||||
this.unsafe = unsafe;
|
||||
}
|
||||
|
||||
|
@ -109,14 +109,27 @@ public final class NioDatagramChannel
|
||||
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
|
||||
* on the Operation Systems default which will be chosen.
|
||||
*/
|
||||
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) {
|
||||
this(newSocket(provider, ipFamily));
|
||||
}
|
||||
|
@ -67,11 +67,21 @@ public class NioServerSocketChannel extends AbstractNioMessageChannel
|
||||
* Create a new instance
|
||||
*/
|
||||
public NioServerSocketChannel() {
|
||||
this(DEFAULT_SELECTOR_PROVIDER);
|
||||
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance using the given {@link SelectorProvider}.
|
||||
*/
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -23,8 +23,6 @@ import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.local.LocalChannel;
|
||||
import io.netty.channel.local.LocalServerChannel;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
class BaseChannelTest {
|
||||
@ -66,18 +64,6 @@ class BaseChannelTest {
|
||||
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) {
|
||||
String actual = loggingHandler.getLog();
|
||||
assertEquals(expected, actual);
|
||||
@ -90,4 +76,5 @@ class BaseChannelTest {
|
||||
void setInterest(LoggingHandler.Event... events) {
|
||||
loggingHandler.setInterest(events);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user