IChannelHandler Replace( AbstractChannelHandlerContext ctx, IChannelHandler newHandler) { Contract.Requires(ctx != this.head && ctx != this.tail); lock (this.head) { var newCtx = new DefaultChannelHandlerContext(this, null, null, newHandler); CheckMultiplicity(newCtx); AbstractChannelHandlerContext prev = ctx.Prev; AbstractChannelHandlerContext next = ctx.Next; newCtx.Prev = prev; newCtx.Next = next; // Finish the replacement of oldCtx with newCtx in the linked list. // Note that this doesn't mean events will be sent to the new handler immediately // because we are currently at the event handler thread and no more than one handler methods can be invoked // at the same time (we ensured that in replace().) prev.Next = newCtx; next.Prev = newCtx; // update the reference to the replacement so forward of buffered content will work correctly ctx.Prev = newCtx; ctx.Next = newCtx; // Invoke newHandler.handlerAdded() first (i.e. before oldHandler.handlerRemoved() is invoked) // because callHandlerRemoved() will trigger inboundBufferUpdated() or flush() on newHandler and those // event handlers must be called after handlerAdded(). this.CallHandlerAdded(newCtx); this.CallHandlerRemoved(ctx); return(ctx.Handler); } }
public IChannelPipeline AddBefore(IChannelHandlerInvoker invoker, string baseName, string name, IChannelHandler handler) { IEventExecutor executor; AbstractChannelHandlerContext newCtx; AbstractChannelHandlerContext ctx; bool inEventLoop; lock (this) { CheckMultiplicity(handler); ctx = this.GetContextOrThrow(baseName); newCtx = new DefaultChannelHandlerContext(this, invoker, this.FilterName(name, handler), handler); executor = this.ExecutorSafe(invoker); // If the executor is null it means that the channel was not registered on an eventloop yet. // In this case we add the context to the pipeline and add a task that will call // ChannelHandler.handlerAdded(...) once the channel is registered. if (executor == null) { AddBefore0(ctx, newCtx); this.CallHandlerCallbackLater(newCtx, true); return(this); } inEventLoop = executor.InEventLoop; if (inEventLoop) { AddBefore0(ctx, newCtx); } } if (inEventLoop) { this.CallHandlerAdded0(newCtx); } else { executor.SubmitAsync(() => { lock (this) { AddBefore0(ctx, newCtx); } this.CallHandlerAdded0(newCtx); return(0); }).Wait(); } return(this); }
IChannelHandler Replace(AbstractChannelHandlerContext ctx, string newName, IChannelHandler newHandler) { Contract.Requires(ctx != this.head && ctx != this.tail); Task future; lock (this.head) { if (newName == null) { newName = ctx.Name; } else if (!ctx.Name.Equals(newName, StringComparison.Ordinal)) { newName = this.FilterName(newName, newHandler); } var newCtx = new DefaultChannelHandlerContext(this, ctx.Invoker, newName, newHandler); if (!newCtx.Channel.Registered || newCtx.Executor.InEventLoop) { this.ReplaceUnsafe(ctx, newName, newCtx); return(ctx.Handler); } else { string finalNewName = newName; future = newCtx.Executor.SubmitAsync( () => { lock (this.head) { this.ReplaceUnsafe(ctx, finalNewName, newCtx); } return(TaskEx.Completed); }); } } // Run the following 'waiting' code outside of the above synchronized block // in order to avoid deadlock future.Wait(); return(ctx.Handler); }
public IChannelPipeline AddLast(IChannelHandler handler) { Contract.Requires(handler != null); var newCtx = new DefaultChannelHandlerContext(this, null, null, handler); CheckMultiplicity(newCtx); AbstractChannelHandlerContext prev = this.tail.Prev; newCtx.Prev = prev; newCtx.Next = this.tail; prev.Next = newCtx; this.tail.Prev = newCtx; this.CallHandlerAdded(newCtx); return(this); }
public IChannelPipeline AddFirst(IChannelHandler handler) { Contract.Requires(handler != null); lock (this.head) { var newCtx = new DefaultChannelHandlerContext(this, null, null, handler); CheckMultiplicity(newCtx); AbstractChannelHandlerContext nextCtx = this.head.Next; newCtx.Prev = this.head; newCtx.Next = nextCtx; this.head.Next = newCtx; nextCtx.Prev = newCtx; this.CallHandlerAdded(newCtx); } return(this); }
public IChannelPipeline AddFirst(IChannelHandlerInvoker invoker, string name, IChannelHandler handler) { Contract.Requires(handler != null); lock (this.head) { name = this.FilterName(name, handler); var newCtx = new DefaultChannelHandlerContext(this, invoker, name, handler); CheckMultiplicity(newCtx); AbstractChannelHandlerContext nextCtx = this.head.Next; newCtx.Prev = this.head; newCtx.Next = nextCtx; this.head.Next = newCtx; nextCtx.Prev = newCtx; this.nameContextMap.Add(name, newCtx); this.CallHandlerAdded(newCtx); } return(this); }
IChannelHandler Replace(AbstractChannelHandlerContext ctx, string newName, IChannelHandler newHandler) { Contract.Assert(ctx != this.head && ctx != this.tail); AbstractChannelHandlerContext newCtx; IEventExecutor executor; bool inEventLoop; lock (this) { CheckMultiplicity(newHandler); if (newName == null) { newName = ctx.Name; } else if (!ctx.Name.Equals(newName, StringComparison.Ordinal)) { newName = this.FilterName(newName, newHandler); } newCtx = new DefaultChannelHandlerContext(this, ctx.invoker, newName, newHandler); executor = this.ExecutorSafe(ctx.invoker); // If the executor is null it means that the channel was not registered on an eventloop yet. // In this case we replace the context in the pipeline // and add a task that will call ChannelHandler.handlerAdded(...) and // ChannelHandler.handlerRemoved(...) once the channel is registered. if (executor == null) { Replace0(ctx, newCtx); this.CallHandlerCallbackLater(newCtx, true); this.CallHandlerCallbackLater(ctx, false); return(ctx.Handler); } inEventLoop = executor.InEventLoop; if (inEventLoop) { Replace0(ctx, newCtx); } } if (inEventLoop) { // Invoke newHandler.handlerAdded() first (i.e. before oldHandler.handlerRemoved() is invoked) // because callHandlerRemoved() will trigger channelRead() or flush() on newHandler and those // event handlers must be called after handlerAdded(). this.CallHandlerAdded0(newCtx); this.CallHandlerRemoved0(ctx); } else { executor.SubmitAsync(() => { lock (this) { Replace0(ctx, newCtx); } // Invoke newHandler.handlerAdded() first (i.e. before oldHandler.handlerRemoved() is invoked) // because callHandlerRemoved() will trigger channelRead() or flush() on newHandler and // those event handlers must be called after handlerAdded(). this.CallHandlerAdded0(newCtx); this.CallHandlerRemoved0(ctx); return(0); }).Wait(); } return(ctx.Handler); }