static void AddBefore0(FABHandlerContext ctx, FABHandlerContext newCtx) { newCtx.Prev = ctx.Prev; newCtx.Next = ctx; ctx.Prev.Next = newCtx; ctx.Prev = newCtx; }
static void AddAfter0(FABHandlerContext ctx, FABHandlerContext newCtx) { newCtx.Prev = ctx; newCtx.Next = ctx.Next; ctx.Next.Prev = newCtx; ctx.Next = newCtx; }
public IFABChannelPipeline AddAfter(IEventExecutorGroup group, string baseName, string name, IFABChannelHandler handler) { Contract.Requires(handler != null); FABHandlerContext newCtx; lock (this) { CheckMultiplicity(handler); FABHandlerContext ctx = this.GetContextOrThrow(baseName); newCtx = this.NewContext(group, this.FilterName(name, handler), handler); IEventExecutor executor = this.ExecutorSafe(newCtx.executor); AddAfter0(ctx, newCtx); // If the executor is null it means that the channel was not registered on an eventloop yet. // In this case we remove the context from the pipeline and add a task that will call // ChannelHandler.handlerRemoved(...) once the channel is registered. if (executor == null) { this.CallHandlerCallbackLater(newCtx, true); return(this); } if (!executor.InEventLoop) { executor.Execute(CallHandlerAddedAction, this, newCtx); return(this); } } this.CallHandlerAdded0(newCtx); return(this); }
public sealed override string ToString() { StringBuilder buf = new StringBuilder() .Append(this.GetType().Name) .Append('{'); FABHandlerContext ctx = this.head.Next; while (true) { if (ctx == this.tail) { break; } buf.Append('(') .Append(ctx.Name) .Append(" = ") .Append(ctx.Handler.GetType().Name) .Append(')'); ctx = ctx.Next; if (ctx == this.tail) { break; } buf.Append(", "); } buf.Append('}'); return(buf.ToString()); }
FABHandlerContext Remove(FABHandlerContext ctx) { Contract.Assert(ctx != this.head && ctx != this.tail); lock (this) { IEventExecutor executor = this.ExecutorSafe(ctx.executor); Remove0(ctx); // If the executor is null it means that the channel was not registered on an eventloop yet. // In this case we remove the context from the pipeline and add a task that will call // ChannelHandler.handlerRemoved(...) once the channel is registered. if (executor == null) { this.CallHandlerCallbackLater(ctx, false); return(ctx); } if (!executor.InEventLoop) { executor.Execute((s, c) => ((FABChannelPipeline)s).CallHandlerRemoved0((FABHandlerContext)c), this, ctx); return(ctx); } } this.CallHandlerRemoved0(ctx); return(ctx); }
void DestroyDown(XThread currentThread, FABHandlerContext ctx, bool inEventLoop) { // We have reached at tail; now traverse backwards. FABHandlerContext headContext = this.head; while (true) { if (ctx == headContext) { break; } IEventExecutor executor = ctx.Executor; if (inEventLoop || executor.IsInEventLoop(currentThread)) { lock (this) { Remove0(ctx); this.CallHandlerRemoved0(ctx); } } else { executor.Execute((self, c) => ((FABChannelPipeline)self).DestroyDown(XThread.CurrentThread, (FABHandlerContext)c, true), this, ctx); break; } ctx = ctx.Prev; inEventLoop = false; } }
protected override Task WriteAsync(FABHandlerContext ctx, object msg) { Task result = base.WriteAsync(ctx, msg); ctx.InvokeFlush(); return(result); }
public static WriteTask NewInstance(FABHandlerContext ctx, object msg, TaskCompletionSource promise) { WriteTask task = Recycler.Take(); Init(task, ctx, msg, promise); return(task); }
protected static void Init(AbstractWriteTask task, FABHandlerContext ctx, object msg, TaskCompletionSource promise) { task.ctx = ctx; task.msg = msg; task.promise = promise; if (EstimateTaskSizeOnSubmit) { FABChannelOutboundBuffer buffer = ctx.Channel.Unsafe.OutboundBuffer; // Check for null as it may be set to null if the channel is closed already if (buffer != null) { task.size = ctx.pipeline.EstimatorHandle.Size(msg) + WriteTaskOverhead; buffer.IncrementPendingOutboundBytes(task.size); } else { task.size = 0; } } else { task.size = 0; } }
IFABChannelHandler Replace(FABHandlerContext ctx, string newName, IFABChannelHandler newHandler) { Contract.Requires(newHandler != null); Contract.Assert(ctx != this.head && ctx != this.tail); FABHandlerContext newCtx; lock (this) { CheckMultiplicity(newHandler); if (newName == null) { newName = this.GenerateName(newHandler); } else { bool sameName = ctx.Name.Equals(newName, StringComparison.Ordinal); if (!sameName) { this.CheckDuplicateName(newName); } } newCtx = this.NewContext(ctx.executor, newName, newHandler); IEventExecutor executor = this.ExecutorSafe(ctx.executor); Replace0(ctx, newCtx); // If the executor is null it means that the channel was not registered on an event loop yet. // In this case we replace the context in the pipeline // and add a task that will signal handler it was added or removed // once the channel is registered. if (executor == null) { this.CallHandlerCallbackLater(newCtx, true); this.CallHandlerCallbackLater(ctx, false); return(ctx.Handler); } if (!executor.InEventLoop) { executor.Execute(() => { // Indicate new handler was added first (i.e. before old handler removed) // because "removed" will trigger ChannelRead() or Flush() on newHandler and // those event handlers must be called after handler was signaled "added". this.CallHandlerAdded0(newCtx); this.CallHandlerRemoved0(ctx); }); return(ctx.Handler); } } // Indicate new handler was added first (i.e. before old handler removed) // because "removed" will trigger ChannelRead() or Flush() on newHandler and // those event handlers must be called after handler was signaled "added". this.CallHandlerAdded0(newCtx); this.CallHandlerRemoved0(ctx); return(ctx.Handler); }
public override void ChannelActive(IFABChannelHandlerContext context) { if (this.context == null) { this.context = (FABHandlerContext)context; } base.ChannelActive(context); }
static void Remove0(FABHandlerContext context) { FABHandlerContext prev = context.Prev; FABHandlerContext next = context.Next; prev.Next = next; next.Prev = prev; }
public override void Flush(IFABChannelHandlerContext context) { context.Flush(); if (this.context == null) { this.context = (FABHandlerContext)context; } }
void AddLast0(FABHandlerContext newCtx) { FABHandlerContext prev = this.tail.Prev; newCtx.Prev = prev; newCtx.Next = this.tail; prev.Next = newCtx; this.tail.Prev = newCtx; }
void AddFirst0(FABHandlerContext newCtx) { FABHandlerContext nextCtx = this.head.Next; newCtx.Prev = this.head; newCtx.Next = nextCtx; this.head.Next = newCtx; nextCtx.Prev = newCtx; }
FABHandlerContext FindContextOutbound() { FABHandlerContext ctx = this; do { ctx = ctx.Prev; }while ((ctx.SkipPropagationFlags & SkipFlags.Outbound) == SkipFlags.Outbound); return(ctx); }
public Task DeregisterAsync() { // todo: check for cancellation FABHandlerContext next = this.FindContextOutbound(); IEventExecutor nextExecutor = next.Executor; return(nextExecutor.InEventLoop ? next.InvokeDeregisterAsync() : SafeExecuteOutboundAsync(nextExecutor, () => next.InvokeDeregisterAsync())); }
IEnumerator <IFABChannelHandler> IEnumerable <IFABChannelHandler> .GetEnumerator() { FABHandlerContext current = this.head; while (current != null) { yield return(current.Handler); current = current.Next; } }
public FABChannelPipeline(FABChannel channel) { Contract.Requires(channel != null); this.channel = channel; this.tail = new TailContext(this); this.head = new HeadContext(this); this.head.Next = this.tail; this.tail.Prev = this.head; }
internal static void InvokeChannelInactive(FABHandlerContext next) { IEventExecutor nextExecutor = next.Executor; if (nextExecutor.InEventLoop) { next.InvokeChannelInactive(); } else { nextExecutor.Execute(c => ((FABHandlerContext)c).InvokeChannelInactive(), next); } }
public Task ConnectAsync(EndPoint remoteAddress, EndPoint localAddress) { FABHandlerContext next = this.FindContextOutbound(); Contract.Requires(remoteAddress != null); // todo: check for cancellation IEventExecutor nextExecutor = next.Executor; return(nextExecutor.InEventLoop ? next.InvokeConnectAsync(remoteAddress, localAddress) : SafeExecuteOutboundAsync(nextExecutor, () => next.InvokeConnectAsync(remoteAddress, localAddress))); }
FABHandlerContext Context0(string name) { FABHandlerContext context = this.head.Next; while (context != this.tail) { if (context.Name.Equals(name, StringComparison.Ordinal)) { return(context); } context = context.Next; } return(null); }
internal static void InvokeUserEventTriggered(FABHandlerContext next, object evt) { Contract.Requires(evt != null); IEventExecutor nextExecutor = next.Executor; if (nextExecutor.InEventLoop) { next.InvokeUserEventTriggered(evt); } else { nextExecutor.Execute(InvokeUserEventTriggeredAction, next, evt); } }
internal static void InvokeChannelReadComplete(FABHandlerContext next) { IEventExecutor nextExecutor = next.Executor; if (nextExecutor.InEventLoop) { next.InvokeChannelReadComplete(); } else { // todo: consider caching task nextExecutor.Execute(InvokeChannelReadCompleteAction, next); } }
internal static void InvokeChannelWritabilityChanged(FABHandlerContext next) { IEventExecutor nextExecutor = next.Executor; if (nextExecutor.InEventLoop) { next.InvokeChannelWritabilityChanged(); } else { // todo: consider caching task nextExecutor.Execute(InvokeChannelWritabilityChangedAction, next); } }
public IFABChannelHandlerContext Flush() { FABHandlerContext next = this.FindContextOutbound(); IEventExecutor nextExecutor = next.Executor; if (nextExecutor.InEventLoop) { next.InvokeFlush(); } else { nextExecutor.Execute(InvokeFlushAction, next); } return(this); }
public Task DisconnectAsync() { if (!this.Channel.Metadata.HasDisconnect) { return(this.CloseAsync()); } // todo: check for cancellation FABHandlerContext next = this.FindContextOutbound(); IEventExecutor nextExecutor = next.Executor; return(nextExecutor.InEventLoop ? next.InvokeDisconnectAsync() : SafeExecuteOutboundAsync(nextExecutor, () => next.InvokeDisconnectAsync())); }
internal static void InvokeChannelRead(FABHandlerContext next, object msg) { Contract.Requires(msg != null); object m = next.pipeline.Touch(msg, next); IEventExecutor nextExecutor = next.Executor; if (nextExecutor.InEventLoop) { next.InvokeChannelRead(m); } else { nextExecutor.Execute(InvokeChannelReadAction, next, msg); } }
public IFABChannelHandlerContext Read() { FABHandlerContext next = this.FindContextOutbound(); IEventExecutor nextExecutor = next.Executor; if (nextExecutor.InEventLoop) { next.InvokeRead(); } else { // todo: consider caching task nextExecutor.Execute(InvokeReadAction, next); } return(this); }
public Task BindAsync(EndPoint localAddress) { Contract.Requires(localAddress != null); // todo: check for cancellation //if (!validatePromise(ctx, promise, false)) { // // promise cancelled // return; //} FABHandlerContext next = this.FindContextOutbound(); IEventExecutor nextExecutor = next.Executor; return(nextExecutor.InEventLoop ? next.InvokeBindAsync(localAddress) : SafeExecuteOutboundAsync(nextExecutor, () => next.InvokeBindAsync(localAddress))); }