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); }
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); }
public void Flush() { ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; if (outboundBuffer == null) { return; } outboundBuffer.AddFlush(); Flush0(); }
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; } }
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); }
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); }
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(); }
/// <summary> /// Flush the content of the given buffer to the remote peer. /// </summary> protected abstract void DoWrite(ChannelOutboundBuffer input);