public override ValueTask WriteAsync(ReadOnlyMemory <byte> buffer, CancellationToken cancellationToken = default) { CheckWriteArguments(); if (buffer.IsEmpty) { return(ValueTask.CompletedTask); // return immediately if no bytes to write; no need for overhead. } SerialStreamWriteRequest result = new SerialStreamWriteRequest(cancellationToken, buffer); _writeQueue.Enqueue(result); EnsureIOLoopRunning(); return(new ValueTask(result.Task)); }
public override Task WriteAsync(byte[] array, int offset, int count, CancellationToken cancellationToken) { CheckWriteArguments(array, offset, count); if (count == 0) { return(Task.CompletedTask); // return immediately if no bytes to write; no need for overhead. } ReadOnlyMemory <byte> buffer = new ReadOnlyMemory <byte>(array, offset, count); SerialStreamWriteRequest result = new SerialStreamWriteRequest(cancellationToken, buffer); _writeQueue.Enqueue(result); EnsureIOLoopRunning(); return(result.Task); }
private unsafe int ProcessWrite(SerialStreamIORequest r) { SerialStreamWriteRequest writeRequest = (SerialStreamWriteRequest)r; ReadOnlySpan <byte> buff = writeRequest.Buffer.Span; fixed(byte *bufPtr = buff) { // assumes dequeue-ing happens on a single thread int numBytes = Interop.Serial.Write(_handle, bufPtr, buff.Length); if (numBytes <= 0) { Interop.ErrorInfo lastError = Interop.Sys.GetLastErrorInfo(); // ignore EWOULDBLOCK since we handle timeout elsewhere // numBytes == 0 means that there might be an error if (lastError.Error != Interop.Error.SUCCESS && lastError.Error != Interop.Error.EWOULDBLOCK) { r.Complete(Interop.GetIOException(lastError)); } } else { writeRequest.ProcessBytes(numBytes); if (writeRequest.Buffer.Length == 0) { writeRequest.Complete(); } return(numBytes); } } return(0); }