// 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);
}
}