コード例 #1
0
        /// <remarks>PORT NOTE: matches behavior of NioEventLoop.processSelectedKey</remarks>
        static void OnIoCompleted(object sender, SocketAsyncEventArgs args)
        {
            var operation = (SocketChannelAsyncOperation)args;
            AbstractSocketChannel channel = operation.Channel;
            var        @unsafe            = (ISocketChannelUnsafe)channel.Unsafe;
            IEventLoop eventLoop          = channel.EventLoop;

            switch (args.LastOperation)
            {
            case SocketAsyncOperation.Accept:
                if (eventLoop.InEventLoop)
                {
                    @unsafe.FinishRead(operation);
                }
                else
                {
                    eventLoop.Execute(ReadCallbackAction, @unsafe, operation);
                }
                break;

            case SocketAsyncOperation.Connect:
                if (eventLoop.InEventLoop)
                {
                    @unsafe.FinishConnect(operation);
                }
                else
                {
                    eventLoop.Execute(ConnectCallbackAction, @unsafe, operation);
                }
                break;

            case SocketAsyncOperation.Receive:
            case SocketAsyncOperation.ReceiveFrom:
                if (eventLoop.InEventLoop)
                {
                    @unsafe.FinishRead(operation);
                }
                else
                {
                    eventLoop.Execute(ReadCallbackAction, @unsafe, operation);
                }
                break;

            case SocketAsyncOperation.Send:
            case SocketAsyncOperation.SendTo:
                if (eventLoop.InEventLoop)
                {
                    @unsafe.FinishWrite(operation);
                }
                else
                {
                    eventLoop.Execute(WriteCallbackAction, @unsafe, operation);
                }
                break;

            default:
                // todo: think of a better way to comm exception
                throw new ArgumentException("The last operation completed on the socket was not expected");
            }
        }
コード例 #2
0
        public Task ShutdownOutputAsync()
        {
            var tcs = new TaskCompletionSource();
            // todo: use closeExecutor if available
            //Executor closeExecutor = ((TcpSocketChannelUnsafe) unsafe()).closeExecutor();
            //if (closeExecutor != null) {
            //    closeExecutor.execute(new OneTimeTask() {

            //        public void run() {
            //            shutdownOutput0(promise);
            //        }
            //    });
            //} else {
            IEventLoop loop = this.EventLoop;

            if (loop.InEventLoop)
            {
                this.ShutdownOutput0(tcs);
            }
            else
            {
                loop.Execute(promise => this.ShutdownOutput0((TaskCompletionSource)promise), tcs);
            }
            //}
            return(tcs.Task);
        }
コード例 #3
0
 public virtual async Task <bool> ReleaseAsync(IChannel channel)
 {
     if (channel is null)
     {
         ThrowHelper.ThrowArgumentNullException(ExceptionArgument.channel);
     }
     try
     {
         IEventLoop loop = channel.EventLoop;
         if (loop.InEventLoop)
         {
             return(await DoReleaseChannel(channel));
         }
         else
         {
             var promise = new TaskCompletionSource <bool>();
             loop.Execute(DoReleaseChannel, channel, promise);
             return(await promise.Task);
         }
     }
     catch (Exception)
     {
         CloseChannel(channel);
         throw;
     }
 }
        public async ValueTask <bool> ReleaseAsync(IChannel channel)
        {
            Contract.Requires(channel != null);

            log.Debug("ReleaseAsync for " + channel.Id);

            try
            {
                IEventLoop loop = channel.EventLoop;

                log.Debug("ReleaseAsync -0- for " + loop.InEventLoop);

                if (loop.InEventLoop)
                {
                    return(await this.DoReleaseChannel(channel));
                }
                else
                {
                    var promise = new TaskCompletionSource <bool>();
                    loop.Execute(this.DoReleaseChannel, channel, promise);
                    return(await promise.Task);
                }
            }
            catch (Exception)
            {
                CloseChannel(channel);
                throw;
            }
        }
コード例 #5
0
        void DispatchCallback()
        {
            var observers = _observers.ToArray();

            _queued = false;

            foreach (var observer in observers)
            {
                _loop.Execute(observer.Trigger);
            }
        }
コード例 #6
0
            public override void ChannelActive(IChannelHandlerContext ctx)
            {
                IEventLoop loop = _group.GetNext();

                if (_sameEventLoop)
                {
                    Deregister(ctx, loop);
                }
                else
                {
                    loop.Execute(() => Deregister(ctx, loop));
                }
            }
コード例 #7
0
            public Task RegisterAsync(IEventLoop eventLoop)
            {
                Contract.Requires(eventLoop != null);
                if (this._channel.Registered)
                {
                    return(TaskEx.FromException(new InvalidOperationException("registered to an event loop already")));
                }
                if (!this._channel.IsCompatible(eventLoop))
                {
                    return
                        (TaskEx.FromException(
                             new InvalidOperationException("incompatible event loop type: " + eventLoop.GetType().Name)));
                }

                // It's necessary to reuse the wrapped eventloop object. Otherwise the user will end up with multiple
                // objects that do not share a common state.
                if (this._channel._eventLoop == null)
                {
                    this._channel._eventLoop = new PausableChannelEventLoop(this._channel, eventLoop);
                }
                else
                {
                    this._channel._eventLoop.Unwrapped = eventLoop;
                }

                var promise = new TaskCompletionSource();

                if (eventLoop.InEventLoop)
                {
                    this.Register0(promise);
                }
                else
                {
                    try
                    {
                        eventLoop.Execute(() => this.Register0(promise));
                    }
                    catch (Exception ex)
                    {
                        Logger.Warning(
                            "Force-closing a channel whose registration task was not accepted by an event loop: {0}; Cause: {1}",
                            _channel,
                            ex);
                        CloseForcibly();
                        _channel._closeTask.TryComplete();
                        PromiseUtil.SafeSetFailure(promise, ex, Logger);
                    }
                }

                return(promise.Task);
            }
コード例 #8
0
            public Task RegisterAsync(IEventLoop eventLoop)
            {
                if (eventLoop is null)
                {
                    ThrowHelper.ThrowArgumentNullException(ExceptionArgument.eventLoop);
                }

                var ch = _channel;

                if (ch.Registered)
                {
                    return(ThrowHelper.ThrowInvalidOperationException_RegisteredToEventLoopAlready());
                }

                if (!ch.IsCompatible(eventLoop))
                {
                    return(ThrowHelper.ThrowInvalidOperationException_IncompatibleEventLoopType(eventLoop));
                }

                _ = Interlocked.Exchange(ref ch.eventLoop, eventLoop);

                var promise = ch.NewPromise();

                if (eventLoop.InEventLoop)
                {
                    Register0(promise);
                }
                else
                {
                    try
                    {
                        eventLoop.Execute(RegisterAction, this, promise);
                    }
                    catch (Exception ex)
                    {
                        if (Logger.WarnEnabled)
                        {
                            Logger.ForceClosingAChannel(ch, ex);
                        }
                        CloseForcibly();
                        ch._closeFuture.Complete();
                        Util.SafeSetFailure(promise, ex, Logger);
                    }
                }

                return(promise.Task);
            }
        public async virtual ValueTask <IChannel> AcquireNewOr(long timeout)
        {
            IChannel chl;
            bool     b = this.store.TryDequeue(out chl);


            this.timeout = timeout;
            if (!b)
            {
                Bootstrap bs = this.bootstrap.Clone();
                //Bootstrap bs =  new Bootstrap();
                bs.Attribute(PoolKey, this);

                log.Debug(" ... try get parent pool channel ... " + parentPool);
                try
                {
                    IChannel chnl = await parentPool.AcquireAsync();

                    log.Debug(" ... Channel " + chnl);

                    await ConnectChannel(chnl, timeout);

                    return(chnl);
                }
                catch (Exception e)
                {
                    log.Error("Something went wromg here: .. " + e.Message);
                }

                return(null);
            }

            IEventLoop eventLoop = chl.EventLoop;

            if (eventLoop.InEventLoop)
            {
                return(await this.DoHealthCheck(chl, timeout));
            }
            else
            {
                var completionSource = new TaskCompletionSource <IChannel>();
                eventLoop.Execute(this.DoHealthCheck, chl, completionSource);
                return(await completionSource.Task);
            }
            // return acquire(bootstrap.Config().group().next().newPromise<IChannel>());
        }
コード例 #10
0
        public void GracefulShutdownAfterStart()
        {
            IEventLoop     loop  = NewEventLoopGroup().GetNext();
            CountdownEvent latch = new CountdownEvent(1);

            loop.Execute(() => latch.Signal());

            // Wait for the event loop thread to start.
            Assert.True(latch.Wait(TimeSpan.FromMinutes(1)));

            // Request the event loop thread to stop.
            loop.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(200), TimeSpan.FromSeconds(3));

            // Wait until the event loop is terminated.
            Assert.True(loop.TerminationCompletion.Wait(TimeSpan.FromMilliseconds(500)));

            AssertRejection(loop);
        }
コード例 #11
0
        public virtual ValueTask <IChannel> AcquireAsync()
        {
            if (!this.TryPollChannel(out IChannel channel))
            {
                Bootstrap bs = this.Bootstrap.Clone();
                bs.Attribute(PoolKey, this);
                return(new ValueTask <IChannel>(this.ConnectChannel(bs)));
            }

            IEventLoop eventLoop = channel.EventLoop;

            if (eventLoop.InEventLoop)
            {
                return(this.DoHealthCheck(channel));
            }
            else
            {
                var completionSource = new TaskCompletionSource <IChannel>();
                eventLoop.Execute(this.DoHealthCheck, channel, completionSource);
                return(new ValueTask <IChannel>(completionSource.Task));
            }
        }
コード例 #12
0
        public void FireNextRead(object msg)
        {
            IEventLoop loop = _channel.Loop;

            if (loop.InCurrentThread())
            {
                if (Next != null)
                {
                    Next.Handler.ChannelRead(Next, msg);
                }
            }
            else
            {
                loop.Execute(new SimpleRunnable(() =>
                {
                    if (Next != null)
                    {
                        Next.Handler.ChannelRead(Next, msg);
                    }
                }));
            }
        }
コード例 #13
0
        public void FireNextInactive()
        {
            IEventLoop loop = _channel.Loop;

            if (loop.InCurrentThread())
            {
                if (Next != null)
                {
                    Next.Handler.ChannelInactive(Next);
                }
            }
            else
            {
                loop.Execute(new SimpleRunnable(() =>
                {
                    if (Next != null)
                    {
                        Next.Handler.ChannelInactive(Next);
                    }
                }));
            }
        }
コード例 #14
0
        public void FireNextAccept(object accepter)
        {
            IEventLoop loop = _channel.Loop;

            if (loop.InCurrentThread())
            {
                if (Next != null)
                {
                    Next.Handler.ChannelAccept(Next, accepter);
                }
            }
            else
            {
                loop.Execute(new SimpleRunnable(() =>
                {
                    if (Next != null)
                    {
                        Next.Handler.ChannelAccept(Next, accepter);
                    }
                }));
            }
        }
コード例 #15
0
        public void FirePreWrite(object msg)
        {
            IEventLoop loop = _channel.Loop;

            if (loop.InCurrentThread())
            {
                if (Prev != null)
                {
                    Prev.Handler.ChannelWrite(Prev, msg);
                }
            }
            else
            {
                loop.Execute(new SimpleRunnable(() =>
                {
                    if (Prev != null)
                    {
                        Prev.Handler.ChannelWrite(Prev, msg);
                    }
                }));
            }
        }
コード例 #16
0
 /// <summary>
 ///     Set read pending to <c>false</c>.
 /// </summary>
 protected internal void ClearReadPending()
 {
     if (this.Registered)
     {
         IEventLoop eventLoop = this.EventLoop;
         if (eventLoop.InEventLoop)
         {
             this.ClearReadPending0();
         }
         else
         {
             eventLoop.Execute(channel => ((AbstractSocketChannel)channel).ClearReadPending0(), this);
         }
     }
     else
     {
         // Best effort if we are not registered yet clear ReadPending. This happens during channel initialization.
         // NB: We only set the boolean field instead of calling ClearReadPending0(), because the SelectionKey is
         // not set yet so it would produce an assertion failure.
         this.ReadPending = false;
     }
 }
コード例 #17
0
            public Task RegisterAsync(IEventLoop eventLoop)
            {
                Contract.Requires(eventLoop != null);

                if (this.channel.Registered)
                {
                    return(TaskEx.FromException(new InvalidOperationException("registered to an event loop already")));
                }

                if (!this.channel.IsCompatible(eventLoop))
                {
                    return(TaskEx.FromException(new InvalidOperationException("incompatible event loop type: " + eventLoop.GetType().Name)));
                }

                this.channel.eventLoop = eventLoop;

                var promise = new TaskCompletionSource();

                if (eventLoop.InEventLoop)
                {
                    this.Register0(promise);
                }
                else
                {
                    try
                    {
                        eventLoop.Execute((u, p) => ((AbstractUnsafe)u).Register0((TaskCompletionSource)p), this, promise);
                    }
                    catch (Exception ex)
                    {
                        Logger.Warn("Force-closing a channel whose registration task was not accepted by an event loop: {}", this.channel, ex);
                        this.CloseForcibly();
                        this.channel.closeFuture.Complete();
                        Util.SafeSetFailure(promise, ex, Logger);
                    }
                }

                return(promise.Task);
            }
コード例 #18
0
 public void Execute(Action action)
 {
     ThrowIfNotRunning();
     _workerThread.Execute(action);
 }
コード例 #19
0
 public void Execute(Action action)
 {
     ThrowIfDisposed();
     _workerThread.Execute(action);
 }
コード例 #20
0
ファイル: LocalChannel.cs プロジェクト: ywscr/SpanNetty
        protected override void DoClose()
        {
            var peer     = Volatile.Read(ref v_peer);
            var oldState = Volatile.Read(ref v_state);

            try
            {
                if (oldState != State.Closed)
                {
                    // Update all internal state before the closeFuture is notified.
                    var thisLocalAddr = Volatile.Read(ref v_localAddress);
                    if (thisLocalAddr is object)
                    {
                        if (Parent is null)
                        {
                            LocalChannelRegistry.Unregister(thisLocalAddr);
                        }
                        _ = Interlocked.Exchange(ref v_localAddress, null);
                    }

                    // State change must happen before finishPeerRead to ensure writes are released either in doWrite or
                    // channelRead.
                    _ = Interlocked.Exchange(ref v_state, State.Closed);

                    // Preserve order of event and force a read operation now before the close operation is processed.
                    if (SharedConstants.False < (uint)Volatile.Read(ref v_writeInProgress) && peer is object)
                    {
                        FinishPeerRead(peer);
                    }

                    TaskCompletionSource promise = Volatile.Read(ref v_connectPromise);
                    if (promise is object)
                    {
                        // Use tryFailure() instead of setFailure() to avoid the race against cancel().
                        _ = promise.TrySetException(DoCloseClosedChannelException);
                        _ = Interlocked.Exchange(ref v_connectPromise, null);
                    }
                }

                if (peer is object)
                {
                    _ = Interlocked.Exchange(ref v_peer, null);
                    // Always call peer.eventLoop().execute() even if peer.eventLoop().inEventLoop() is true.
                    // This ensures that if both channels are on the same event loop, the peer's channelInActive
                    // event is triggered *after* this peer's channelInActive event
                    IEventLoop peerEventLoop = peer.EventLoop;
                    bool       peerIsActive  = peer.IsActive;
                    try
                    {
                        peerEventLoop.Execute(() => peer.TryClose(peerIsActive));
                    }
                    catch (Exception cause)
                    {
                        Logger.Warn("Releasing Inbound Queues for channels {}-{} because exception occurred!", this, peer, cause);

                        if (peerEventLoop.InEventLoop)
                        {
                            peer.ReleaseInboundBuffers();
                        }
                        else
                        {
                            // inboundBuffers is a SPSC so we may leak if the event loop is shutdown prematurely or
                            // rejects the close Runnable but give a best effort.
                            _ = peer.CloseAsync();
                        }
                        throw;
                    }
                }
            }
            finally
            {
                // Release all buffers if the Channel was already registered in the past and if it was not closed before.
                if (oldState != State.Closed)
                {
                    // We need to release all the buffers that may be put into our inbound queue since we closed the Channel
                    // to ensure we not leak any memory. This is fine as it basically gives the same guarantees as TCP which
                    // means even if the promise was notified before its not really guaranteed that the "remote peer" will
                    // see the buffer at all.
                    ReleaseInboundBuffers();
                }
            }
        }
コード例 #21
0
ファイル: AbstractChannel.cs プロジェクト: helios-io/helios
            public Task RegisterAsync(IEventLoop eventLoop)
            {
                Contract.Requires(eventLoop != null);
                if (this._channel.Registered)
                {
                    return TaskEx.FromException(new InvalidOperationException("registered to an event loop already"));
                }
                if (!this._channel.IsCompatible(eventLoop))
                {
                    return
                        TaskEx.FromException(
                            new InvalidOperationException("incompatible event loop type: " + eventLoop.GetType().Name));
                }

                // It's necessary to reuse the wrapped eventloop object. Otherwise the user will end up with multiple
                // objects that do not share a common state.
                if (this._channel._eventLoop == null)
                {
                    this._channel._eventLoop = new PausableChannelEventLoop(this._channel, eventLoop);
                }
                else
                {
                    this._channel._eventLoop.Unwrapped = eventLoop;
                }

                var promise = new TaskCompletionSource();

                if (eventLoop.InEventLoop)
                {
                    this.Register0(promise);
                }
                else
                {
                    try
                    {
                        eventLoop.Execute(() => this.Register0(promise));
                    }
                    catch (Exception ex)
                    {
                        Logger.Warning(
                            "Force-closing a channel whose registration task was not accepted by an event loop: {0}; Cause: {1}",
                            _channel,
                            ex);
                        CloseForcibly();
                        _channel._closeTask.TryComplete();
                        PromiseUtil.SafeSetFailure(promise, ex, Logger);
                    }
                }

                return promise.Task;
            }
コード例 #22
0
        protected override void DoClose()
        {
            var peer     = this.peer;
            var oldState = this.state;

            try
            {
                if (oldState != State.Closed)
                {
                    // Update all internal state before the closeFuture is notified.
                    if (this.localAddress != null)
                    {
                        if (this.Parent == null)
                        {
                            LocalChannelRegistry.Unregister(this.localAddress);
                        }
                        this.localAddress = null;
                    }

                    // State change must happen before finishPeerRead to ensure writes are released either in doWrite or
                    // channelRead.
                    this.state = State.Closed;

                    // Preserve order of event and force a read operation now before the close operation is processed.
                    this.FinishPeerRead(this);

                    TaskCompletionSource promise = this.connectPromise;
                    if (promise != null)
                    {
                        // Use tryFailure() instead of setFailure() to avoid the race against cancel().
                        promise.TrySetException(DoCloseClosedChannelException);
                        this.connectPromise = null;
                    }
                }

                if (peer != null)
                {
                    this.peer = null;
                    // Need to execute the close in the correct EventLoop (see https://github.com/netty/netty/issues/1777).
                    // Also check if the registration was not done yet. In this case we submit the close to the EventLoop
                    // to make sure its run after the registration completes
                    // (see https://github.com/netty/netty/issues/2144).
                    IEventLoop peerEventLoop = peer.EventLoop;
                    bool       peerIsActive  = peer.Active;
                    if (peerEventLoop.InEventLoop && !this.registerInProgress)
                    {
                        peer.TryClose(peerIsActive);
                    }
                    else
                    {
                        try
                        {
                            peerEventLoop.Execute(() => peer.TryClose(peerIsActive));
                        }
                        catch (Exception cause)
                        {
                            Logger.Warn("Releasing Inbound Queues for channels {}-{} because exception occurred!", this, peer, cause);

                            if (peerEventLoop.InEventLoop)
                            {
                                peer.ReleaseInboundBuffers();
                            }
                            else
                            {
                                // inboundBuffers is a SPSC so we may leak if the event loop is shutdown prematurely or
                                // rejects the close Runnable but give a best effort.
                                peer.CloseAsync();
                            }
                            throw;
                        }
                    }
                }
            }
            finally
            {
                // Release all buffers if the Channel was already registered in the past and if it was not closed before.
                if (oldState != State.Closed)
                {
                    // We need to release all the buffers that may be put into our inbound queue since we closed the Channel
                    // to ensure we not leak any memory. This is fine as it basically gives the same guarantees as TCP which
                    // means even if the promise was notified before its not really guaranteed that the "remote peer" will
                    // see the buffer at all.
                    this.ReleaseInboundBuffers();
                }
            }
        }
コード例 #23
0
ファイル: AbstractChannel.cs プロジェクト: nayato/DotNetty
            public Task RegisterAsync(IEventLoop eventLoop)
            {
                Contract.Requires(eventLoop != null);

                if (this.channel.Registered)
                {
                    return TaskEx.FromException(new InvalidOperationException("registered to an event loop already"));
                }

                if (!this.channel.IsCompatible(eventLoop))
                {
                    return TaskEx.FromException(new InvalidOperationException("incompatible event loop type: " + eventLoop.GetType().Name));
                }

                this.channel.eventLoop = eventLoop;

                var promise = new TaskCompletionSource();

                if (eventLoop.InEventLoop)
                {
                    this.Register0(promise);
                }
                else
                {
                    try
                    {
                        eventLoop.Execute((u, p) => ((AbstractUnsafe)u).Register0((TaskCompletionSource)p), this, promise);
                    }
                    catch (Exception ex)
                    {
                        Logger.Warn("Force-closing a channel whose registration task was not accepted by an event loop: {}", this.channel, ex);
                        this.CloseForcibly();
                        this.channel.closeFuture.Complete();
                        Util.SafeSetFailure(promise, ex, Logger);
                    }
                }

                return promise.Task;
            }