// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Buffers; using System.IO; using System.Threading; using System.Threading.Tasks; namespace EpicGames.Horde.Compute { /// /// Low-level interface for transferring data /// public abstract class ComputeTransport : IAsyncDisposable { /// /// Writes data to the underlying transport /// /// Buffer to be written /// Cancellation token for the operation public abstract ValueTask SendAsync(ReadOnlySequence buffer, CancellationToken cancellationToken); /// /// Reads data from the underlying transport into an output buffer /// /// Buffer to read into /// Cancellation token for the operation public abstract ValueTask RecvAsync(Memory buffer, CancellationToken cancellationToken); /// /// Indicate that all data has been read and written to the transport layer, and that there will be no more calls to send/recv /// /// Cancellation token for the operation public abstract ValueTask MarkCompleteAsync(CancellationToken cancellationToken); /// public abstract ValueTask DisposeAsync(); /// /// Fill the given buffer with data /// /// Buffer to read into /// Cancellation token for the operation public async ValueTask RecvFullAsync(Memory buffer, CancellationToken cancellationToken) { int read = 0; while (read < buffer.Length) { int partialRead = await RecvAsync(buffer.Slice(read, buffer.Length - read), cancellationToken); if (partialRead == 0) { throw new EndOfStreamException(); } read += partialRead; } } /// /// Fill the given buffer with data /// /// Buffer to read into /// Cancellation token for the operation public async ValueTask RecvOptionalAsync(Memory buffer, CancellationToken cancellationToken) { try { int read = await RecvAsync(buffer, cancellationToken); if (read == 0) { return false; } if (read < buffer.Length) { await RecvFullAsync(buffer.Slice(read), cancellationToken); } return true; } catch (EndOfStreamException) { return false; } } /// /// Writes data to the underlying transport /// /// Buffer to be written /// Cancellation token for the operation public ValueTask SendAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken) => SendAsync(new ReadOnlySequence(buffer), cancellationToken); } }