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;
            }
        }
Beispiel #7
0
            protected override Task WriteAsync(FABHandlerContext ctx, object msg)
            {
                Task result = base.WriteAsync(ctx, msg);

                ctx.InvokeFlush();
                return(result);
            }
Beispiel #8
0
            public static WriteTask NewInstance(FABHandlerContext ctx, object msg, TaskCompletionSource promise)
            {
                WriteTask task = Recycler.Take();

                Init(task, ctx, msg, promise);
                return(task);
            }
Beispiel #9
0
            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;
                }
            }
Beispiel #10
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);
        }
Beispiel #11
0
 public override void ChannelActive(IFABChannelHandlerContext context)
 {
     if (this.context == null)
     {
         this.context = (FABHandlerContext)context;
     }
     base.ChannelActive(context);
 }
Beispiel #12
0
        static void Remove0(FABHandlerContext context)
        {
            FABHandlerContext prev = context.Prev;
            FABHandlerContext next = context.Next;

            prev.Next = next;
            next.Prev = prev;
        }
Beispiel #13
0
 public override void Flush(IFABChannelHandlerContext context)
 {
     context.Flush();
     if (this.context == null)
     {
         this.context = (FABHandlerContext)context;
     }
 }
Beispiel #14
0
        void AddLast0(FABHandlerContext newCtx)
        {
            FABHandlerContext prev = this.tail.Prev;

            newCtx.Prev    = prev;
            newCtx.Next    = this.tail;
            prev.Next      = newCtx;
            this.tail.Prev = newCtx;
        }
Beispiel #15
0
        void AddFirst0(FABHandlerContext newCtx)
        {
            FABHandlerContext nextCtx = this.head.Next;

            newCtx.Prev    = this.head;
            newCtx.Next    = nextCtx;
            this.head.Next = newCtx;
            nextCtx.Prev   = newCtx;
        }
Beispiel #16
0
        FABHandlerContext FindContextOutbound()
        {
            FABHandlerContext ctx = this;

            do
            {
                ctx = ctx.Prev;
            }while ((ctx.SkipPropagationFlags & SkipFlags.Outbound) == SkipFlags.Outbound);
            return(ctx);
        }
Beispiel #17
0
        public Task DeregisterAsync()
        {
            // todo: check for cancellation
            FABHandlerContext next         = this.FindContextOutbound();
            IEventExecutor    nextExecutor = next.Executor;

            return(nextExecutor.InEventLoop
                ? next.InvokeDeregisterAsync()
                : SafeExecuteOutboundAsync(nextExecutor, () => next.InvokeDeregisterAsync()));
        }
Beispiel #18
0
        IEnumerator <IFABChannelHandler> IEnumerable <IFABChannelHandler> .GetEnumerator()
        {
            FABHandlerContext current = this.head;

            while (current != null)
            {
                yield return(current.Handler);

                current = current.Next;
            }
        }
Beispiel #19
0
        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;
        }
Beispiel #20
0
        internal static void InvokeChannelInactive(FABHandlerContext next)
        {
            IEventExecutor nextExecutor = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                next.InvokeChannelInactive();
            }
            else
            {
                nextExecutor.Execute(c => ((FABHandlerContext)c).InvokeChannelInactive(), next);
            }
        }
Beispiel #21
0
        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)));
        }
Beispiel #22
0
        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);
        }
Beispiel #23
0
        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);
            }
        }
Beispiel #24
0
        internal static void InvokeChannelReadComplete(FABHandlerContext next)
        {
            IEventExecutor nextExecutor = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                next.InvokeChannelReadComplete();
            }
            else
            {
                // todo: consider caching task
                nextExecutor.Execute(InvokeChannelReadCompleteAction, next);
            }
        }
Beispiel #25
0
        internal static void InvokeChannelWritabilityChanged(FABHandlerContext next)
        {
            IEventExecutor nextExecutor = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                next.InvokeChannelWritabilityChanged();
            }
            else
            {
                // todo: consider caching task
                nextExecutor.Execute(InvokeChannelWritabilityChangedAction, next);
            }
        }
Beispiel #26
0
        public IFABChannelHandlerContext Flush()
        {
            FABHandlerContext next         = this.FindContextOutbound();
            IEventExecutor    nextExecutor = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                next.InvokeFlush();
            }
            else
            {
                nextExecutor.Execute(InvokeFlushAction, next);
            }
            return(this);
        }
Beispiel #27
0
        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()));
        }
Beispiel #28
0
        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);
            }
        }
Beispiel #29
0
        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);
        }
Beispiel #30
0
        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)));
        }