Task ISocketOutput.WriteAsync(ArraySegment <byte> buffer, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { _connection.Abort(); _cancelled = true; return(TaskUtilities.GetCancelledTask(cancellationToken)); } else if (_cancelled) { return(TaskUtilities.CompletedTask); } return(WriteAsync(buffer, cancellationToken)); }
private Task ValidateState(CancellationToken cancellationToken) { switch (_state) { case FrameStreamState.Open: if (cancellationToken.IsCancellationRequested) { return(TaskUtilities.GetCancelledTask(cancellationToken)); } break; case FrameStreamState.Closed: throw new ObjectDisposedException(nameof(FrameResponseStream)); case FrameStreamState.Aborted: if (cancellationToken.IsCancellationRequested) { // Aborted state only throws on write if cancellationToken requests it return(TaskUtilities.GetCancelledTask(cancellationToken)); } break; } return(null); }
public Task WriteAsync( ArraySegment <byte> buffer, CancellationToken cancellationToken, bool socketShutdownSend = false, bool socketDisconnect = false, bool isSync = false) { TaskCompletionSource <object> tcs = null; var scheduleWrite = false; lock (_contextLock) { if (_socket.IsClosed) { Service.Logger.Log(_lastWriteError); return(TaskUtilities.CompletedTask); } if (buffer.Count > 0) { var tail = ProducingStart(); if (tail.IsDefault) { return(TaskUtilities.CompletedTask); } tail.CopyFrom(buffer); // We do our own accounting below ProducingCompleteNoPreComplete(tail); } if (_nextWriteContext == null) { if (_writeContextPool.Count > 0) { _nextWriteContext = _writeContextPool.Dequeue(); } else { _nextWriteContext = new WriteContext(this); } } if (socketShutdownSend) { _nextWriteContext.SocketShutdownSend = true; } if (socketDisconnect) { _nextWriteContext.SocketDisconnect = true; } if (_lastWriteError == null && _tasksPending.Count == 0 && _numBytesPreCompleted + buffer.Count <= _maxBytesPreCompleted) { // Complete the write task immediately if all previous write tasks have been completed, // the buffers haven't grown too large, and the last write to the socket succeeded. _numBytesPreCompleted += buffer.Count; } else { if (cancellationToken.CanBeCanceled) { if (cancellationToken.IsCancellationRequested) { _connection.Abort(); _cancelled = true; return(TaskUtilities.GetCancelledTask(cancellationToken)); } else { // immediate write, which is not eligable for instant completion above tcs = new TaskCompletionSource <object>(); _tasksPending.Enqueue(new WaitingTask() { CancellationToken = cancellationToken, CancellationRegistration = cancellationToken.Register(_connectionCancellation, this), BytesToWrite = buffer.Count, CompletionSource = tcs }); } } else { tcs = new TaskCompletionSource <object>(); _tasksPending.Enqueue(new WaitingTask() { IsSync = isSync, BytesToWrite = buffer.Count, CompletionSource = tcs }); } } if (!_postingWrite && _ongoingWrites < _maxPendingWrites) { _postingWrite = true; _ongoingWrites++; scheduleWrite = true; } } if (scheduleWrite) { ScheduleWrite(); } // Return TaskCompletionSource's Task if set, otherwise completed Task return(tcs?.Task ?? TaskUtilities.CompletedTask); }