Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove allocation of state machine in QuicStream.WriteAsync #103902

Merged
merged 5 commits into from
Jun 26, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -351,29 +351,32 @@ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationTo
/// <param name="completeWrites">Notifies the peer about gracefully closing the write side, i.e.: sends FIN flag with the data.</param>
public ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, bool completeWrites, CancellationToken cancellationToken = default)
rzikm marked this conversation as resolved.
Show resolved Hide resolved
{
ObjectDisposedException.ThrowIf(_disposed == 1, this);
if (_disposed == 1)
{
return ValueTask.FromException(new ObjectDisposedException(nameof(QuicStream)));
rzikm marked this conversation as resolved.
Show resolved Hide resolved
}

if (!_canWrite)
{
throw new InvalidOperationException(SR.net_quic_writing_notallowed);
return ValueTask.FromException(new InvalidOperationException(SR.net_quic_writing_notallowed));
}

if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Info(this, $"{this} Stream writing memory of '{buffer.Length}' bytes while {(completeWrites ? "completing" : "not completing")} writes.");
}

if (_sendTcs.IsCompleted)
if (_sendTcs.IsCompleted && cancellationToken.IsCancellationRequested)
{
// Special case exception type for pre-canceled token while we've already transitioned to a final state and don't need to abort write.
// It must happen before we try to get the value task, since the task source is versioned and each instance must be awaited.
cancellationToken.ThrowIfCancellationRequested();
return ValueTask.FromCanceled(cancellationToken);
}

// Concurrent call, this one lost the race.
if (!_sendTcs.TryGetValueTask(out ValueTask valueTask, this, cancellationToken))
{
throw new InvalidOperationException(SR.Format(SR.net_io_invalidnestedcall, "write"));
return ValueTask.FromException(new InvalidOperationException(SR.Format(SR.net_io_invalidnestedcall, "write")));
}

// No need to call anything since we already have a result, most likely an exception.
Expand Down
Loading