Merge pull request #4634 from khellang/copy-to-async-buffer-size

Added CopyToAsync overload using default buffer size
This commit is contained in:
Stephen Toub 2017-09-29 08:39:40 -04:00 коммит произвёл GitHub
Родитель 55c9db39ce 3c53151d76
Коммит a410be2def
1 изменённых файлов: 39 добавлений и 50 удалений

Просмотреть файл

@ -95,36 +95,7 @@ namespace System.IO
public Task CopyToAsync(Stream destination)
{
int bufferSize = DefaultCopyBufferSize;
if (CanSeek)
{
long length = Length;
long position = Position;
if (length <= position) // Handles negative overflows
{
// If we go down this branch, it means there are
// no bytes left in this stream.
// Ideally we would just return Task.CompletedTask here,
// but CopyToAsync(Stream, int, CancellationToken) was already
// virtual at the time this optimization was introduced. So
// if it does things like argument validation (checking if destination
// is null and throwing an exception), then await fooStream.CopyToAsync(null)
// would no longer throw if there were no bytes left. On the other hand,
// we also can't roll our own argument validation and return Task.CompletedTask,
// because it would be a breaking change if the stream's override didn't throw before,
// or in a different order. So for simplicity, we just set the bufferSize to 1
// (not 0 since the default implementation throws for 0) and forward to the virtual method.
bufferSize = 1;
}
else
{
long remaining = length - position;
if (remaining > 0) // In the case of a positive overflow, stick to the default size
bufferSize = (int)Math.Min(bufferSize, remaining);
}
}
int bufferSize = GetCopyBufferSize();
return CopyToAsync(destination, bufferSize);
}
@ -134,6 +105,13 @@ namespace System.IO
return CopyToAsync(destination, bufferSize, CancellationToken.None);
}
public Task CopyToAsync(Stream destination, CancellationToken cancellationToken)
{
int bufferSize = GetCopyBufferSize();
return CopyToAsync(destination, bufferSize, cancellationToken);
}
public virtual Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
{
StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
@ -162,26 +140,7 @@ namespace System.IO
// the current position.
public void CopyTo(Stream destination)
{
int bufferSize = DefaultCopyBufferSize;
if (CanSeek)
{
long length = Length;
long position = Position;
if (length <= position) // Handles negative overflows
{
// No bytes left in stream
// Call the other overload with a bufferSize of 1,
// in case it's made virtual in the future
bufferSize = 1;
}
else
{
long remaining = length - position;
if (remaining > 0) // In the case of a positive overflow, stick to the default size
bufferSize = (int)Math.Min(bufferSize, remaining);
}
}
int bufferSize = GetCopyBufferSize();
CopyTo(destination, bufferSize);
}
@ -198,6 +157,36 @@ namespace System.IO
}
}
private int GetCopyBufferSize()
{
int bufferSize = DefaultCopyBufferSize;
if (CanSeek)
{
long length = Length;
long position = Position;
if (length <= position) // Handles negative overflows
{
// There are no bytes left in the stream to copy.
// However, because CopyTo{Async} is virtual, we need to
// ensure that any override is still invoked to provide its
// own validation, so we use the smallest legal buffer size here.
bufferSize = 1;
}
else
{
long remaining = length - position;
if (remaining > 0)
{
// In the case of a positive overflow, stick to the default size
bufferSize = (int)Math.Min(bufferSize, remaining);
}
}
}
return bufferSize;
}
public virtual void Close()
{
Dispose(true);