private DefaultChannelHandlerContext remove( final DefaultChannelHandlerContext ctx, final boolean forward) { assert ctx != head && ctx != tail; DefaultChannelHandlerContext context; Future<?> future; synchronized (this) { if (!ctx.channel().isRegistered() || ctx.executor().inEventLoop()) { remove0(ctx, forward); return ctx; } else { future = ctx.executor() .submit( new Runnable() { @Override public void run() { synchronized (DefaultChannelPipeline.this) { remove0(ctx, forward); } } }); context = ctx; } } // Run the following 'waiting' code outside of the above synchronized block // in order to avoid deadlock waitForFuture(future); return context; }
@Override public ChannelPipeline addAfter( EventExecutorGroup group, String baseName, final String name, ChannelHandler handler) { final DefaultChannelHandlerContext ctx; final DefaultChannelHandlerContext newCtx; synchronized (this) { ctx = getContextOrDie(baseName); checkDuplicateName(name); newCtx = new DefaultChannelHandlerContext(this, group, name, handler); if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) { addAfter0(name, ctx, newCtx); return this; } } // Run the following 'waiting' code outside of the above synchronized block // in order to avoid deadlock newCtx.executeOnEventLoop( new Runnable() { @Override public void run() { synchronized (DefaultChannelPipeline.this) { checkDuplicateName(name); addAfter0(name, ctx, newCtx); } } }); return this; }
private ChannelHandler replace( final DefaultChannelHandlerContext ctx, final String newName, ChannelHandler newHandler, final boolean forward) { assert ctx != head && ctx != tail; Future<?> future; synchronized (this) { boolean sameName = ctx.name().equals(newName); if (!sameName) { checkDuplicateName(newName); } final DefaultChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, ctx.executor, newName, newHandler); if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) { replace0(ctx, newName, newCtx, forward); return ctx.handler(); } else { future = newCtx .executor() .submit( new Runnable() { @Override public void run() { synchronized (DefaultChannelPipeline.this) { replace0(ctx, newName, newCtx, forward); } } }); } } // Run the following 'waiting' code outside of the above synchronized block // in order to avoid deadlock waitForFuture(future); return ctx.handler(); }