Beispiel #1
0
            public static WriteTask NewInstance(
                IChannelHandlerContext ctx, object msg, TaskCompletionSource promise)
            {
                WriteTask task = Pool.Value.Take();

                task.ctx     = ctx;
                task.msg     = msg;
                task.promise = promise;

                if (EstimateTaskSizeOnSubmit)
                {
                    ChannelOutboundBuffer 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 = ((AbstractChannel)ctx.Channel).EstimatorHandle.Size(msg) + WriteTaskOverhead;
                        buffer.IncrementPendingOutboundBytes(task.size);
                    }
                    else
                    {
                        task.size = 0;
                    }
                }
                else
                {
                    task.size = 0;
                }

                return(task);
            }
Beispiel #2
0
            public Task CloseAsync() //CancellationToken cancellationToken)
            {
                var promise = new TaskCompletionSource();

                if (!promise.SetUncancellable())
                {
                    return(promise.Task);
                }
                //if (cancellationToken.IsCancellationRequested)
                //{
                //    return TaskEx.Cancelled;
                //}

                if (this.outboundBuffer == null)
                {
                    // Only needed if no VoidChannelPromise.
                    if (promise != TaskCompletionSource.Void)
                    {
                        // This means close() was called before so we just register a listener and return
                        return(this._channel._closeTask.Task);
                    }
                    return(promise.Task);
                }

                if (this._channel._closeTask.Task.IsCompleted)
                {
                    // Closed already.
                    PromiseUtil.SafeSetSuccess(promise, Logger);
                    return(promise.Task);
                }

                bool wasActive = this._channel.IsActive;
                ChannelOutboundBuffer buffer = this.outboundBuffer;

                this.outboundBuffer = null; // Disallow adding any messages and flushes to outboundBuffer.

                try
                {
                    // Close the channel and fail the queued messages input all cases.
                    this.DoClose0(promise);
                }
                finally
                {
                    // Fail all the queued messages.
                    buffer.FailFlushed(ClosedChannelException.Instance, false);
                    buffer.Close(ClosedChannelException.Instance);
                }
                if (this.inFlush0)
                {
                    this.InvokeLater(() => this.FireChannelInactiveAndDeregister(wasActive));
                }
                else
                {
                    this.FireChannelInactiveAndDeregister(wasActive);
                }


                return(promise.Task);
            }
Beispiel #3
0
            public void Flush()
            {
                ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;

                if (outboundBuffer == null)
                {
                    return;
                }

                outboundBuffer.AddFlush();
                Flush0();
            }
Beispiel #4
0
            protected virtual void Flush0()
            {
                if (inFlush0)
                {
                    // Avoid re-entrance
                    return;
                }

                ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;

                if (outboundBuffer == null || outboundBuffer.IsEmpty)
                {
                    return;
                }

                this.inFlush0 = true;

                // Mark all pending write requests as failure if the channel is inactive.
                if (!this._channel.IsActive)
                {
                    try
                    {
                        if (this._channel.IsOpen)
                        {
                            outboundBuffer.FailFlushed(NotYetConnectedException.Instance, true);
                        }
                        else
                        {
                            // Do not trigger channelWritabilityChanged because the channel is closed already.
                            outboundBuffer.FailFlushed(ClosedChannelException.Instance, false);
                        }
                    }
                    finally
                    {
                        this.inFlush0 = false;
                    }
                    return;
                }

                try
                {
                    this._channel.DoWrite(outboundBuffer);
                }
                catch (Exception t)
                {
                    outboundBuffer.FailFlushed(t, true);
                }
                finally
                {
                    this.inFlush0 = false;
                }
            }
Beispiel #5
0
 protected AbstractUnsafe(AbstractChannel channel)
 {
     this._channel            = channel;
     InvokeWritabilityChanged = () =>
     {
         if (channel.EventLoop.InEventLoop)
         {
             channel.Pipeline.FireChannelWritabilityChanged();
         }
         else
         {
             channel.EventLoop.Execute(InvokeWritabilityChangedUnsafe, channel);
         }
     };
     this.outboundBuffer = new ChannelOutboundBuffer(channel, InvokeWritabilityChanged);
 }
Beispiel #6
0
            public Task WriteAsync(object msg)
            {
                ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;

                if (outboundBuffer == null)
                {
                    // If the outboundBuffer is null we know the channel was closed and so
                    // need to fail the future right away. If it is not null the handling of the rest
                    // will be done input flush0()
                    // See https://github.com/netty/netty/issues/2362

                    // release message now to prevent resource-leak
                    // TODO: referencing counting
                    ReferenceCountUtil.SafeRelease(msg);
                    return(TaskEx.FromException(ClosedChannelException.Instance));
                }

                int size;

                try
                {
                    msg  = this._channel.FilterOutboundMessage(msg);
                    size = this._channel.EstimatorHandle.Size(msg);
                    if (size < 0)
                    {
                        size = 0;
                    }
                }
                catch (Exception t)
                {
                    ReferenceCountUtil.SafeRelease(msg);

                    return(TaskEx.FromException(t));
                }

                var promise = new TaskCompletionSource();

                outboundBuffer.AddMessage(msg, size, promise);
                return(promise.Task);
            }
Beispiel #7
0
            public void Run()
            {
                try
                {
                    ChannelOutboundBuffer buffer = this.ctx.Channel.Unsafe.OutboundBuffer;
                    // Check for null as it may be set to null if the channel is closed already
                    if (EstimateTaskSizeOnSubmit)
                    {
                        buffer?.DecrementPendingOutboundBytes(this.size);
                    }
                    ChannelHandlerInvokerUtil.InvokeWriteAsyncNow(this.ctx, this.msg).LinkOutcome(this.promise);
                }
                finally
                {
                    // Set to null so the GC can collect them directly
                    this.ctx     = null;
                    this.msg     = null;
                    this.promise = null;

                    // recycle
                    _handle.Free(this);
                }
            }
 protected override void DoWrite(ChannelOutboundBuffer input)
 {
     throw new NotSupportedException();
 }
Beispiel #9
0
 /// <summary>
 /// Flush the content of the given buffer to the remote peer.
 /// </summary>
 protected abstract void DoWrite(ChannelOutboundBuffer input);