Simplify DefaultChannelPipeline
This commit is contained in:
parent
b742dcc209
commit
b6fcf3acc4
@ -143,7 +143,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
private final Runnable nextCtxFireInboundBufferUpdatedTask = new Runnable() {
|
private final Runnable nextCtxFireInboundBufferUpdatedTask = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
DefaultChannelHandlerContext next = nextContext(
|
DefaultChannelHandlerContext next = findContextInbound(
|
||||||
DefaultChannelHandlerContext.this.next, FLAG_STATE_HANDLER);
|
DefaultChannelHandlerContext.this.next, FLAG_STATE_HANDLER);
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
next.fillBridge();
|
next.fillBridge();
|
||||||
@ -188,7 +188,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultChannelHandlerContext nextCtx = nextContext(ctx.next, FLAG_STATE_HANDLER);
|
DefaultChannelHandlerContext nextCtx = findContextInbound(ctx.next, FLAG_STATE_HANDLER);
|
||||||
if (nextCtx != null) {
|
if (nextCtx != null) {
|
||||||
nextCtx.callFreeInboundBuffer();
|
nextCtx.callFreeInboundBuffer();
|
||||||
} else {
|
} else {
|
||||||
@ -218,7 +218,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultChannelHandlerContext nextCtx = prevContext(ctx.prev, FLAG_OPERATION_HANDLER);
|
DefaultChannelHandlerContext nextCtx = findContextOutbound(ctx.prev, FLAG_OPERATION_HANDLER);
|
||||||
if (nextCtx != null) {
|
if (nextCtx != null) {
|
||||||
nextCtx.callFreeOutboundBuffer();
|
nextCtx.callFreeOutboundBuffer();
|
||||||
}
|
}
|
||||||
@ -941,17 +941,17 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf nextOutboundByteBuffer() {
|
public ByteBuf nextOutboundByteBuffer() {
|
||||||
return pipeline.nextOutboundByteBuffer(prev);
|
return pipeline.findOutboundByteBuffer(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MessageBuf<Object> nextOutboundMessageBuffer() {
|
public MessageBuf<Object> nextOutboundMessageBuffer() {
|
||||||
return pipeline.nextOutboundMessageBuffer(prev);
|
return pipeline.findOutboundMessageBuffer(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fireChannelRegistered() {
|
public void fireChannelRegistered() {
|
||||||
DefaultChannelHandlerContext next = nextContext(this.next, FLAG_STATE_HANDLER);
|
DefaultChannelHandlerContext next = findContextInbound(this.next, FLAG_STATE_HANDLER);
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
EventExecutor executor = next.executor();
|
EventExecutor executor = next.executor();
|
||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
@ -964,7 +964,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fireChannelUnregistered() {
|
public void fireChannelUnregistered() {
|
||||||
DefaultChannelHandlerContext next = nextContext(this.next, FLAG_STATE_HANDLER);
|
DefaultChannelHandlerContext next = findContextInbound(this.next, FLAG_STATE_HANDLER);
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
EventExecutor executor = next.executor();
|
EventExecutor executor = next.executor();
|
||||||
if (executor.inEventLoop() && prev != null) {
|
if (executor.inEventLoop() && prev != null) {
|
||||||
@ -977,7 +977,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fireChannelActive() {
|
public void fireChannelActive() {
|
||||||
DefaultChannelHandlerContext next = nextContext(this.next, FLAG_STATE_HANDLER);
|
DefaultChannelHandlerContext next = findContextInbound(this.next, FLAG_STATE_HANDLER);
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
EventExecutor executor = next.executor();
|
EventExecutor executor = next.executor();
|
||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
@ -990,7 +990,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fireChannelInactive() {
|
public void fireChannelInactive() {
|
||||||
DefaultChannelHandlerContext next = nextContext(this.next, FLAG_STATE_HANDLER);
|
DefaultChannelHandlerContext next = findContextInbound(this.next, FLAG_STATE_HANDLER);
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
EventExecutor executor = next.executor();
|
EventExecutor executor = next.executor();
|
||||||
if (executor.inEventLoop() && prev != null) {
|
if (executor.inEventLoop() && prev != null) {
|
||||||
@ -1085,7 +1085,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fireInboundBufferSuspended() {
|
public void fireInboundBufferSuspended() {
|
||||||
DefaultChannelHandlerContext next = nextContext(this.next, FLAG_STATE_HANDLER);
|
DefaultChannelHandlerContext next = findContextInbound(this.next, FLAG_STATE_HANDLER);
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
EventExecutor executor = next.executor();
|
EventExecutor executor = next.executor();
|
||||||
if (executor.inEventLoop() && prev != null) {
|
if (executor.inEventLoop() && prev != null) {
|
||||||
@ -1138,7 +1138,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
|
public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
|
||||||
return pipeline.bind(prevContext(prev, FLAG_OPERATION_HANDLER), localAddress, promise);
|
return pipeline.bind(findContextOutbound(prev, FLAG_OPERATION_HANDLER), localAddress, promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1148,34 +1148,35 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
|
public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
|
||||||
return pipeline.connect(prevContext(prev, FLAG_OPERATION_HANDLER), remoteAddress, localAddress, promise);
|
return pipeline.connect(
|
||||||
|
findContextOutbound(prev, FLAG_OPERATION_HANDLER), remoteAddress, localAddress, promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture disconnect(ChannelPromise promise) {
|
public ChannelFuture disconnect(ChannelPromise promise) {
|
||||||
return pipeline.disconnect(prevContext(prev, FLAG_OPERATION_HANDLER), promise);
|
return pipeline.disconnect(findContextOutbound(prev, FLAG_OPERATION_HANDLER), promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture close(ChannelPromise promise) {
|
public ChannelFuture close(ChannelPromise promise) {
|
||||||
return pipeline.close(prevContext(prev, FLAG_OPERATION_HANDLER), promise);
|
return pipeline.close(findContextOutbound(prev, FLAG_OPERATION_HANDLER), promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture deregister(ChannelPromise promise) {
|
public ChannelFuture deregister(ChannelPromise promise) {
|
||||||
return pipeline.deregister(prevContext(prev, FLAG_OPERATION_HANDLER), promise);
|
return pipeline.deregister(findContextOutbound(prev, FLAG_OPERATION_HANDLER), promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read() {
|
public void read() {
|
||||||
pipeline.read(prevContext(prev, FLAG_OPERATION_HANDLER));
|
pipeline.read(findContextOutbound(prev, FLAG_OPERATION_HANDLER));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture flush(final ChannelPromise promise) {
|
public ChannelFuture flush(final ChannelPromise promise) {
|
||||||
EventExecutor executor = executor();
|
EventExecutor executor = executor();
|
||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
DefaultChannelHandlerContext prev = prevContext(this.prev, FLAG_OPERATION_HANDLER);
|
DefaultChannelHandlerContext prev = findContextOutbound(this.prev, FLAG_OPERATION_HANDLER);
|
||||||
prev.fillBridge();
|
prev.fillBridge();
|
||||||
pipeline.flush(prev, promise);
|
pipeline.flush(prev, promise);
|
||||||
} else {
|
} else {
|
||||||
@ -1310,11 +1311,11 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture sendFile(FileRegion region) {
|
public ChannelFuture sendFile(FileRegion region) {
|
||||||
return pipeline.sendFile(prevContext(prev, FLAG_OPERATION_HANDLER), region, newPromise());
|
return pipeline.sendFile(findContextOutbound(prev, FLAG_OPERATION_HANDLER), region, newPromise());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture sendFile(FileRegion region, ChannelPromise promise) {
|
public ChannelFuture sendFile(FileRegion region, ChannelPromise promise) {
|
||||||
return pipeline.sendFile(prevContext(prev, FLAG_OPERATION_HANDLER), region, promise);
|
return pipeline.sendFile(findContextOutbound(prev, FLAG_OPERATION_HANDLER), region, promise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,7 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
private final Channel.Unsafe unsafe;
|
private final Channel.Unsafe unsafe;
|
||||||
|
|
||||||
final DefaultChannelHandlerContext head;
|
final DefaultChannelHandlerContext head;
|
||||||
private volatile DefaultChannelHandlerContext tail;
|
final DefaultChannelHandlerContext tail;
|
||||||
private final DefaultChannelHandlerContext tailCtx;
|
|
||||||
|
|
||||||
private final Map<String, DefaultChannelHandlerContext> name2ctx =
|
private final Map<String, DefaultChannelHandlerContext> name2ctx =
|
||||||
new HashMap<String, DefaultChannelHandlerContext>(4);
|
new HashMap<String, DefaultChannelHandlerContext>(4);
|
||||||
@ -66,7 +65,7 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
|
|
||||||
tailCtx = new DefaultChannelHandlerContext(
|
tail = new DefaultChannelHandlerContext(
|
||||||
this, null, null, null, generateName(TAIL_HANDLER), TAIL_HANDLER);
|
this, null, null, null, generateName(TAIL_HANDLER), TAIL_HANDLER);
|
||||||
|
|
||||||
HeadHandler headHandler;
|
HeadHandler headHandler;
|
||||||
@ -82,9 +81,8 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
head = new DefaultChannelHandlerContext(
|
head = new DefaultChannelHandlerContext(
|
||||||
this, null, null, tailCtx, generateName(headHandler), headHandler);
|
this, null, null, tail, generateName(headHandler), headHandler);
|
||||||
tailCtx.prev = head;
|
tail.prev = head;
|
||||||
tail = tailCtx;
|
|
||||||
|
|
||||||
unsafe = channel.unsafe();
|
unsafe = channel.unsafe();
|
||||||
}
|
}
|
||||||
@ -101,16 +99,14 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelPipeline addFirst(EventExecutorGroup group, final String name, ChannelHandler handler) {
|
public ChannelPipeline addFirst(EventExecutorGroup group, final String name, ChannelHandler handler) {
|
||||||
final DefaultChannelHandlerContext nextCtx;
|
|
||||||
final DefaultChannelHandlerContext newCtx;
|
final DefaultChannelHandlerContext newCtx;
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
checkDuplicateName(name);
|
checkDuplicateName(name);
|
||||||
nextCtx = head.next;
|
newCtx = new DefaultChannelHandlerContext(this, group, null, null, name, handler);
|
||||||
newCtx = new DefaultChannelHandlerContext(this, group, head, nextCtx, name, handler);
|
|
||||||
|
|
||||||
if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) {
|
if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) {
|
||||||
addFirst0(name, nextCtx, newCtx);
|
addFirst0(name, newCtx);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,7 +119,7 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
public void run() {
|
public void run() {
|
||||||
synchronized (DefaultChannelPipeline.this) {
|
synchronized (DefaultChannelPipeline.this) {
|
||||||
checkDuplicateName(name);
|
checkDuplicateName(name);
|
||||||
addFirst0(name, nextCtx, newCtx);
|
addFirst0(name, newCtx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -131,19 +127,14 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addFirst0(
|
private void addFirst0(String name, DefaultChannelHandlerContext newCtx) {
|
||||||
final String name, DefaultChannelHandlerContext nextCtx, DefaultChannelHandlerContext newCtx) {
|
|
||||||
callBeforeAdd(newCtx);
|
callBeforeAdd(newCtx);
|
||||||
|
|
||||||
if (nextCtx != null) {
|
DefaultChannelHandlerContext nextCtx = head.next;
|
||||||
nextCtx.prev = newCtx;
|
|
||||||
}
|
|
||||||
if (head.next == tailCtx) {
|
|
||||||
tail = newCtx;
|
|
||||||
newCtx.next = tailCtx;
|
|
||||||
tailCtx.prev = newCtx;
|
|
||||||
}
|
|
||||||
head.next = newCtx;
|
head.next = newCtx;
|
||||||
|
newCtx.prev = head;
|
||||||
|
newCtx.next = nextCtx;
|
||||||
|
nextCtx.prev = newCtx;
|
||||||
|
|
||||||
name2ctx.put(name, newCtx);
|
name2ctx.put(name, newCtx);
|
||||||
|
|
||||||
@ -157,16 +148,14 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelPipeline addLast(EventExecutorGroup group, final String name, ChannelHandler handler) {
|
public ChannelPipeline addLast(EventExecutorGroup group, final String name, ChannelHandler handler) {
|
||||||
final DefaultChannelHandlerContext oldTail;
|
final DefaultChannelHandlerContext newCtx;
|
||||||
final DefaultChannelHandlerContext newTail;
|
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
checkDuplicateName(name);
|
checkDuplicateName(name);
|
||||||
|
|
||||||
oldTail = tail;
|
newCtx = new DefaultChannelHandlerContext(this, group, null, null, name, handler);
|
||||||
newTail = new DefaultChannelHandlerContext(this, group, null, null, name, handler);
|
if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) {
|
||||||
if (!newTail.channel().isRegistered() || newTail.executor().inEventLoop()) {
|
addLast0(name, newCtx);
|
||||||
addLast0(name, oldTail, newTail);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,42 +163,32 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
// Run the following 'waiting' code outside of the above synchronized block
|
// Run the following 'waiting' code outside of the above synchronized block
|
||||||
// in order to avoid deadlock
|
// in order to avoid deadlock
|
||||||
|
|
||||||
newTail.executeOnEventLoop(new Runnable() {
|
newCtx.executeOnEventLoop(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
synchronized (DefaultChannelPipeline.this) {
|
synchronized (DefaultChannelPipeline.this) {
|
||||||
checkDuplicateName(name);
|
checkDuplicateName(name);
|
||||||
addLast0(name, oldTail, newTail);
|
addLast0(name, newCtx);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addLast0(
|
private void addLast0(
|
||||||
final String name, DefaultChannelHandlerContext oldTail, DefaultChannelHandlerContext newTail) {
|
final String name, DefaultChannelHandlerContext newCtx) {
|
||||||
callBeforeAdd(newTail);
|
callBeforeAdd(newCtx);
|
||||||
|
|
||||||
DefaultChannelHandlerContext prev = oldTail.prev;
|
DefaultChannelHandlerContext prev = tail.prev;
|
||||||
if (oldTail == tailCtx) {
|
prev.next = newCtx;
|
||||||
// This is the first handler added
|
newCtx.prev = prev;
|
||||||
tailCtx.prev = newTail;
|
newCtx.next = tail;
|
||||||
newTail.next = tailCtx;
|
tail.prev = newCtx;
|
||||||
prev.next = newTail;
|
|
||||||
newTail.prev = prev;
|
|
||||||
} else {
|
|
||||||
oldTail.next = newTail;
|
|
||||||
newTail.prev = oldTail;
|
|
||||||
|
|
||||||
prev.next = oldTail;
|
name2ctx.put(name, newCtx);
|
||||||
oldTail.prev = prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
tail = newTail;
|
callAfterAdd(newCtx);
|
||||||
name2ctx.put(name, newTail);
|
|
||||||
|
|
||||||
callAfterAdd(newTail);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -273,11 +252,8 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
ctx = getContextOrDie(baseName);
|
ctx = getContextOrDie(baseName);
|
||||||
if (ctx == tail) {
|
|
||||||
return addLast(name, handler);
|
|
||||||
}
|
|
||||||
checkDuplicateName(name);
|
checkDuplicateName(name);
|
||||||
newCtx = new DefaultChannelHandlerContext(this, group, ctx, ctx.next, name, handler);
|
newCtx = new DefaultChannelHandlerContext(this, group, null, null, name, handler);
|
||||||
|
|
||||||
if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) {
|
if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) {
|
||||||
addAfter0(name, ctx, newCtx);
|
addAfter0(name, ctx, newCtx);
|
||||||
@ -306,8 +282,11 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
callBeforeAdd(newCtx);
|
callBeforeAdd(newCtx);
|
||||||
|
|
||||||
|
newCtx.prev = ctx;
|
||||||
|
newCtx.next = ctx.next;
|
||||||
ctx.next.prev = newCtx;
|
ctx.next.prev = newCtx;
|
||||||
ctx.next = newCtx;
|
ctx.next = newCtx;
|
||||||
|
|
||||||
name2ctx.put(name, newCtx);
|
name2ctx.put(name, newCtx);
|
||||||
|
|
||||||
callAfterAdd(newCtx);
|
callAfterAdd(newCtx);
|
||||||
@ -391,52 +370,25 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private DefaultChannelHandlerContext remove(final DefaultChannelHandlerContext ctx) {
|
private DefaultChannelHandlerContext remove(final DefaultChannelHandlerContext ctx) {
|
||||||
|
assert ctx != head && ctx != tail;
|
||||||
|
|
||||||
DefaultChannelHandlerContext context;
|
DefaultChannelHandlerContext context;
|
||||||
Future<?> future;
|
Future<?> future;
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (ctx == tailCtx) {
|
if (!ctx.channel().isRegistered() || ctx.executor().inEventLoop()) {
|
||||||
throw new NoSuchElementException();
|
remove0(ctx);
|
||||||
}
|
return ctx;
|
||||||
if (head == tail) {
|
|
||||||
return null;
|
|
||||||
} else if (ctx == head) {
|
|
||||||
throw new Error(); // Should never happen.
|
|
||||||
} else if (ctx == tail) {
|
|
||||||
if (tail == tailCtx) {
|
|
||||||
throw new NoSuchElementException();
|
|
||||||
}
|
|
||||||
|
|
||||||
final DefaultChannelHandlerContext oldTail = tail;
|
|
||||||
if (!oldTail.channel().isRegistered() || oldTail.executor().inEventLoop()) {
|
|
||||||
removeLast0(oldTail);
|
|
||||||
return oldTail;
|
|
||||||
} else {
|
|
||||||
future = oldTail.executor().submit(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
synchronized (DefaultChannelPipeline.this) {
|
|
||||||
removeLast0(oldTail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
context = oldTail;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!ctx.channel().isRegistered() || ctx.executor().inEventLoop()) {
|
future = ctx.executor().submit(new Runnable() {
|
||||||
remove0(ctx);
|
@Override
|
||||||
return ctx;
|
public void run() {
|
||||||
} else {
|
synchronized (DefaultChannelPipeline.this) {
|
||||||
future = ctx.executor().submit(new Runnable() {
|
remove0(ctx);
|
||||||
@Override
|
}
|
||||||
public void run() {
|
}
|
||||||
synchronized (DefaultChannelPipeline.this) {
|
});
|
||||||
remove0(ctx);
|
context = ctx;
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
context = ctx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,7 +414,7 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelHandler removeFirst() {
|
public ChannelHandler removeFirst() {
|
||||||
if (head.next == tailCtx) {
|
if (head.next == tail) {
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
}
|
}
|
||||||
return remove(head.next).handler();
|
return remove(head.next).handler();
|
||||||
@ -470,44 +422,10 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelHandler removeLast() {
|
public ChannelHandler removeLast() {
|
||||||
final DefaultChannelHandlerContext oldTail;
|
if (head.next == tail) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
synchronized (this) {
|
|
||||||
if (tail == tailCtx) {
|
|
||||||
throw new NoSuchElementException();
|
|
||||||
}
|
|
||||||
oldTail = tail;
|
|
||||||
if (!oldTail.channel().isRegistered() || oldTail.executor().inEventLoop()) {
|
|
||||||
removeLast0(oldTail);
|
|
||||||
return oldTail.handler();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return remove(tail.prev).handler();
|
||||||
// Run the following 'waiting' code outside of the above synchronized block
|
|
||||||
// in order to avoid deadlock
|
|
||||||
|
|
||||||
oldTail.executeOnEventLoop(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
synchronized (DefaultChannelPipeline.this) {
|
|
||||||
removeLast0(oldTail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return oldTail.handler();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeLast0(DefaultChannelHandlerContext oldTail) {
|
|
||||||
callBeforeRemove(oldTail);
|
|
||||||
|
|
||||||
tailCtx.prev = oldTail.prev;
|
|
||||||
oldTail.prev.next = tailCtx;
|
|
||||||
|
|
||||||
tail = oldTail.prev;
|
|
||||||
name2ctx.remove(oldTail.name());
|
|
||||||
|
|
||||||
callBeforeRemove(oldTail);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -530,63 +448,31 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
private ChannelHandler replace(
|
private ChannelHandler replace(
|
||||||
final DefaultChannelHandlerContext ctx, final String newName, ChannelHandler newHandler) {
|
final DefaultChannelHandlerContext ctx, final String newName, ChannelHandler newHandler) {
|
||||||
|
|
||||||
|
assert ctx != head && ctx != tail;
|
||||||
|
|
||||||
Future<?> future;
|
Future<?> future;
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (ctx == tailCtx) {
|
boolean sameName = ctx.name().equals(newName);
|
||||||
throw new NoSuchElementException();
|
if (!sameName) {
|
||||||
|
checkDuplicateName(newName);
|
||||||
}
|
}
|
||||||
if (ctx == head) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
} else if (ctx == tail) {
|
|
||||||
if (tail == tailCtx) {
|
|
||||||
throw new NoSuchElementException();
|
|
||||||
}
|
|
||||||
final DefaultChannelHandlerContext oldTail = tail;
|
|
||||||
final DefaultChannelHandlerContext newTail =
|
|
||||||
new DefaultChannelHandlerContext(this, null, oldTail, null, newName, newHandler);
|
|
||||||
|
|
||||||
if (!oldTail.channel().isRegistered() || oldTail.executor().inEventLoop()) {
|
final DefaultChannelHandlerContext newCtx =
|
||||||
removeLast0(oldTail);
|
new DefaultChannelHandlerContext(this, ctx.executor, null, null, newName, newHandler);
|
||||||
checkDuplicateName(newName);
|
|
||||||
addLast0(newName, tail, newTail);
|
if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) {
|
||||||
return ctx.handler();
|
replace0(ctx, newName, newCtx);
|
||||||
} else {
|
return ctx.handler();
|
||||||
future = oldTail.executor().submit(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
synchronized (DefaultChannelPipeline.this) {
|
|
||||||
removeLast0(oldTail);
|
|
||||||
checkDuplicateName(newName);
|
|
||||||
addLast0(newName, tail, newTail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
boolean sameName = ctx.name().equals(newName);
|
future = newCtx.executor().submit(new Runnable() {
|
||||||
if (!sameName) {
|
@Override
|
||||||
checkDuplicateName(newName);
|
public void run() {
|
||||||
}
|
synchronized (DefaultChannelPipeline.this) {
|
||||||
|
replace0(ctx, newName, newCtx);
|
||||||
DefaultChannelHandlerContext prev = ctx.prev;
|
}
|
||||||
DefaultChannelHandlerContext next = ctx.next;
|
}
|
||||||
|
});
|
||||||
final DefaultChannelHandlerContext newCtx =
|
|
||||||
new DefaultChannelHandlerContext(this, ctx.executor, prev, next, newName, newHandler);
|
|
||||||
|
|
||||||
if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) {
|
|
||||||
replace0(ctx, newName, newCtx);
|
|
||||||
return ctx.handler();
|
|
||||||
} else {
|
|
||||||
future = newCtx.executor().submit(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
synchronized (DefaultChannelPipeline.this) {
|
|
||||||
replace0(ctx, newName, newCtx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -607,6 +493,8 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
callBeforeRemove(ctx);
|
callBeforeRemove(ctx);
|
||||||
callBeforeAdd(newCtx);
|
callBeforeAdd(newCtx);
|
||||||
|
|
||||||
|
newCtx.prev = prev;
|
||||||
|
newCtx.next = next;
|
||||||
prev.next = newCtx;
|
prev.next = newCtx;
|
||||||
next.prev = newCtx;
|
next.prev = newCtx;
|
||||||
|
|
||||||
@ -729,8 +617,8 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelHandler last() {
|
public ChannelHandler last() {
|
||||||
DefaultChannelHandlerContext last = tail;
|
DefaultChannelHandlerContext last = tail.prev;
|
||||||
if (last == tailCtx || last == null) {
|
if (last == head) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return last.handler();
|
return last.handler();
|
||||||
@ -738,8 +626,8 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelHandlerContext lastContext() {
|
public ChannelHandlerContext lastContext() {
|
||||||
DefaultChannelHandlerContext last = tail;
|
DefaultChannelHandlerContext last = tail.prev;
|
||||||
if (last == head || last == null) {
|
if (last == head) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return last;
|
return last;
|
||||||
@ -834,7 +722,7 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
Map<String, ChannelHandler> map = new LinkedHashMap<String, ChannelHandler>();
|
Map<String, ChannelHandler> map = new LinkedHashMap<String, ChannelHandler>();
|
||||||
DefaultChannelHandlerContext ctx = head.next;
|
DefaultChannelHandlerContext ctx = head.next;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (ctx == null || ctx == tailCtx) {
|
if (ctx == tail) {
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
map.put(ctx.name(), ctx.handler());
|
map.put(ctx.name(), ctx.handler());
|
||||||
@ -863,7 +751,7 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
buf.append(')');
|
buf.append(')');
|
||||||
|
|
||||||
ctx = ctx.next;
|
ctx = ctx.next;
|
||||||
if (ctx == null) {
|
if (ctx == tail) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -887,15 +775,15 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> MessageBuf<T> outboundMessageBuffer() {
|
public <T> MessageBuf<T> outboundMessageBuffer() {
|
||||||
return (MessageBuf<T>) nextOutboundMessageBuffer(tail);
|
return (MessageBuf<T>) findOutboundMessageBuffer(tail.prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf outboundByteBuffer() {
|
public ByteBuf outboundByteBuffer() {
|
||||||
return nextOutboundByteBuffer(tail);
|
return findOutboundByteBuffer(tail.prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuf nextOutboundByteBuffer(DefaultChannelHandlerContext ctx) {
|
ByteBuf findOutboundByteBuffer(DefaultChannelHandlerContext ctx) {
|
||||||
final DefaultChannelHandlerContext initialCtx = ctx;
|
final DefaultChannelHandlerContext initialCtx = ctx;
|
||||||
final Thread currentThread = Thread.currentThread();
|
final Thread currentThread = Thread.currentThread();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -931,7 +819,7 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageBuf<Object> nextOutboundMessageBuffer(DefaultChannelHandlerContext ctx) {
|
MessageBuf<Object> findOutboundMessageBuffer(DefaultChannelHandlerContext ctx) {
|
||||||
final DefaultChannelHandlerContext initialCtx = ctx;
|
final DefaultChannelHandlerContext initialCtx = ctx;
|
||||||
final Thread currentThread = Thread.currentThread();
|
final Thread currentThread = Thread.currentThread();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -1333,7 +1221,7 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
if (message instanceof FileRegion) {
|
if (message instanceof FileRegion) {
|
||||||
return sendFile((FileRegion) message, promise);
|
return sendFile((FileRegion) message, promise);
|
||||||
}
|
}
|
||||||
return write(tail, message, promise);
|
return write(tail.prev, message, promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelFuture write(DefaultChannelHandlerContext ctx, final Object message, final ChannelPromise promise) {
|
ChannelFuture write(DefaultChannelHandlerContext ctx, final Object message, final ChannelPromise promise) {
|
||||||
@ -1425,10 +1313,10 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DefaultChannelHandlerContext lastContext(int flag) {
|
DefaultChannelHandlerContext lastContext(int flag) {
|
||||||
return prevContext(tail, flag);
|
return findContextOutbound(tail.prev, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DefaultChannelHandlerContext nextContext(DefaultChannelHandlerContext ctx, int flag) {
|
static DefaultChannelHandlerContext findContextInbound(DefaultChannelHandlerContext ctx, int flag) {
|
||||||
if (ctx == null) {
|
if (ctx == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -1443,7 +1331,7 @@ final class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
return realCtx;
|
return realCtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DefaultChannelHandlerContext prevContext(DefaultChannelHandlerContext ctx, int flag) {
|
static DefaultChannelHandlerContext findContextOutbound(DefaultChannelHandlerContext ctx, int flag) {
|
||||||
if (ctx == null) {
|
if (ctx == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ public class DefaultChannelPipelineTest {
|
|||||||
private static void verifyContextNumber(DefaultChannelPipeline pipeline, int expectedNumber) {
|
private static void verifyContextNumber(DefaultChannelPipeline pipeline, int expectedNumber) {
|
||||||
DefaultChannelHandlerContext ctx = (DefaultChannelHandlerContext) pipeline.firstContext();
|
DefaultChannelHandlerContext ctx = (DefaultChannelHandlerContext) pipeline.firstContext();
|
||||||
int handlerNumber = 0;
|
int handlerNumber = 0;
|
||||||
while (ctx != null) {
|
while (ctx != pipeline.tail) {
|
||||||
handlerNumber++;
|
handlerNumber++;
|
||||||
ctx = ctx.next;
|
ctx = ctx.next;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user