Skip to content

Commit 46c136c

Browse files
authored
Cleanup memory after UnflushedBytes_HandlesLargeValues test (#117115)
Use memory pool that manages single buffer and reuse it each time a buffer is requested
1 parent 69eea4d commit 46c136c

File tree

1 file changed

+84
-6
lines changed

1 file changed

+84
-6
lines changed

src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -360,19 +360,97 @@ public async Task GetMemoryFlushWithACompletedReaderNoops()
360360
Assert.Equal(0, Pipe.Writer.UnflushedBytes);
361361
}
362362

363-
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser), nameof(PlatformDetection.Is64BitProcess))]
363+
[Fact]
364364
public void UnflushedBytes_HandlesLargeValues()
365365
{
366-
PipeWriter writer = PipeWriter.Create(Stream.Null);
367366
int bufferSize = 10000;
367+
using (SingleBufferMemoryPool pool = new(bufferSize))
368+
{
369+
PipeWriter writer = PipeWriter.Create(Stream.Null, new StreamPipeWriterOptions(pool));
370+
371+
while (writer.UnflushedBytes >= 0 && writer.UnflushedBytes <= int.MaxValue)
372+
{
373+
writer.GetMemory(bufferSize);
374+
writer.Advance(bufferSize);
375+
}
376+
377+
Assert.Equal(2147490000, writer.UnflushedBytes);
378+
}
379+
}
380+
381+
internal class SingleBufferMemoryPool : MemoryPool<byte>
382+
{
383+
private readonly int _maxBufferSize;
384+
private byte[] _buffer;
385+
private bool _disposed;
386+
387+
internal SingleBufferMemoryPool(int maxBufferSize)
388+
{
389+
_maxBufferSize = maxBufferSize;
390+
_buffer = new byte[maxBufferSize];
391+
}
392+
393+
public override int MaxBufferSize => _maxBufferSize;
368394

369-
while (writer.UnflushedBytes >= 0 && writer.UnflushedBytes <= int.MaxValue)
395+
public override IMemoryOwner<byte> Rent(int minBufferSize = -1)
370396
{
371-
writer.GetMemory(bufferSize);
372-
writer.Advance(bufferSize);
397+
if (minBufferSize > _maxBufferSize)
398+
{
399+
throw new ArgumentOutOfRangeException(nameof(minBufferSize), $"{nameof(minBufferSize)} should be less than {_maxBufferSize}");
400+
}
401+
402+
return new BufferMemoryOwner(minBufferSize, _maxBufferSize, _buffer);
373403
}
374404

375-
Assert.Equal(2147490000, writer.UnflushedBytes);
405+
protected override void Dispose(bool disposing)
406+
{
407+
if (!_disposed)
408+
{
409+
return;
410+
}
411+
412+
if (disposing)
413+
{
414+
_buffer = null;
415+
}
416+
417+
_disposed = true;
418+
}
419+
}
420+
421+
internal class BufferMemoryOwner : MemoryManager<byte>
422+
{
423+
private int _minBufferSize;
424+
private byte[] _buffer;
425+
private bool _disposed;
426+
427+
public BufferMemoryOwner(int minBufferSize, int maxBufferSize, byte[] buffer)
428+
{
429+
_minBufferSize = minBufferSize <= 0 ? maxBufferSize : minBufferSize;
430+
_buffer = buffer;
431+
}
432+
433+
public override Span<byte> GetSpan() => new(_buffer, 0, _minBufferSize);
434+
435+
public override Memory<byte> Memory => new(_buffer, 0, _minBufferSize);
436+
437+
public override MemoryHandle Pin(int elementIndex = 0) => throw new NotImplementedException();
438+
public override void Unpin() => throw new NotImplementedException();
439+
440+
protected override void Dispose(bool disposing)
441+
{
442+
if (!_disposed)
443+
{
444+
return;
445+
}
446+
447+
if (disposing)
448+
{
449+
_buffer = null;
450+
}
451+
452+
_disposed = true;
453+
}
376454
}
377455
}
378456
}

0 commit comments

Comments
 (0)