Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
PR feedback (#26563)
Browse files Browse the repository at this point in the history
  • Loading branch information
atsushikan authored Jan 25, 2018
1 parent 92df694 commit a398684
Show file tree
Hide file tree
Showing 8 changed files with 523 additions and 2 deletions.
9 changes: 9 additions & 0 deletions src/System.Memory/ref/System.Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,15 @@ public partial struct MemoryHandle : System.IDisposable
public unsafe void* Pointer { get { throw null; } }
public void Dispose() { }
}
public abstract class MemoryPool<T> : IDisposable
{
public static System.Buffers.MemoryPool<T> Shared { get; }
public abstract System.Buffers.OwnedMemory<T> Rent(int minBufferSize=-1);
public abstract int MaxBufferSize { get; }
protected MemoryPool() { throw null; }
public void Dispose() { throw null; }
protected abstract void Dispose(bool disposing);
}
public enum OperationStatus
{
DestinationTooSmall = 1,
Expand Down
6 changes: 5 additions & 1 deletion src/System.Memory/src/System.Memory.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
<Compile Include="System\SpanHelpers.T.cs" />
<Compile Include="System\SpanHelpers.byte.cs" />
<Compile Include="System\ThrowHelper.cs" />
<Compile Include="System\Buffers\ArrayMemoryPool.cs" />
<Compile Include="System\Buffers\ArrayMemoryPool.ArrayMemoryPoolBuffer.cs" />
<Compile Include="System\Buffers\MemoryPool.cs" />
<Compile Include="System\Buffers\OperationStatus.cs" />
<Compile Include="System\Buffers\Binary\Reader.cs" />
<Compile Include="System\Buffers\Binary\ReaderBigEndian.cs" />
Expand Down Expand Up @@ -123,6 +126,7 @@
</Compile>
</ItemGroup>
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true'">
<Reference Include="System.Buffers" />
<Reference Include="System.Diagnostics.Debug" />
<Reference Include="System.Globalization" />
<Reference Include="System.Reflection" />
Expand All @@ -143,4 +147,4 @@
<ProjectReference Include="..\..\System.Numerics.Vectors\src\System.Numerics.Vectors.csproj" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.InteropServices;
#if !netstandard
using Internal.Runtime.CompilerServices;
#else
using System.Runtime.CompilerServices;
#endif

namespace System.Buffers
{
internal sealed partial class ArrayMemoryPool<T> : MemoryPool<T>
{
private sealed class ArrayMemoryPoolBuffer : OwnedMemory<T>
{
private T[] _array;
private int _refCount;

public ArrayMemoryPoolBuffer(int size)
{
_array = ArrayPool<T>.Shared.Rent(size);
}

public sealed override int Length => _array.Length;

public sealed override bool IsDisposed => _array == null;

protected sealed override bool IsRetained => _refCount > 0;

public sealed override Span<T> Span
{
get
{
if (IsDisposed)
ThrowHelper.ThrowObjectDisposedException_ArrayMemoryPoolBuffer();

return _array;
}
}

protected sealed override void Dispose(bool disposing)
{
if (_array != null)
{
ArrayPool<T>.Shared.Return(_array);
_array = null;
}
}

protected
#if netstandard // TryGetArray is exposed as "protected internal". Normally, the rules of C# dictate we override it as "protected" because the base class is
// in a different assembly. Except in the netstandard config where the base class is in the same assembly.
internal
#endif
sealed override bool TryGetArray(out ArraySegment<T> arraySegment)
{
if (IsDisposed)
ThrowHelper.ThrowObjectDisposedException_ArrayMemoryPoolBuffer();

arraySegment = new ArraySegment<T>(_array);
return true;
}

public sealed override MemoryHandle Pin(int byteOffset = 0)
{
unsafe
{
Retain(); // this checks IsDisposed

if (byteOffset != 0 && (((uint)byteOffset) - 1) / Unsafe.SizeOf<T>() >= _array.Length)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.byteOffset);

GCHandle handle = GCHandle.Alloc(_array, GCHandleType.Pinned);
return new MemoryHandle(this, ((byte*)handle.AddrOfPinnedObject()) + byteOffset, handle);
}
}

public sealed override void Retain()
{
if (IsDisposed)
ThrowHelper.ThrowObjectDisposedException_ArrayMemoryPoolBuffer();

_refCount++;
}

public sealed override bool Release()
{
if (IsDisposed)
ThrowHelper.ThrowObjectDisposedException_ArrayMemoryPoolBuffer();

int newRefCount = --_refCount;
if (newRefCount < 0)
ThrowHelper.ThrowInvalidOperationException();

return newRefCount != 0;
}
}
}
}
30 changes: 30 additions & 0 deletions src/System.Memory/src/System/Buffers/ArrayMemoryPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if !netstandard
using Internal.Runtime.CompilerServices;
#else
using System.Runtime.CompilerServices;
#endif

namespace System.Buffers
{
internal sealed partial class ArrayMemoryPool<T> : MemoryPool<T>
{
private const int s_maxBufferSize = int.MaxValue;
public sealed override int MaxBufferSize => s_maxBufferSize;

public sealed override OwnedMemory<T> Rent(int minimumBufferSize = -1)
{
if (minimumBufferSize == -1)
minimumBufferSize = 1 + (4095 / Unsafe.SizeOf<T>());
else if (((uint)minimumBufferSize) > s_maxBufferSize)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.minimumBufferSize);

return new ArrayMemoryPoolBuffer(minimumBufferSize);
}

protected sealed override void Dispose(bool disposing) {} // ArrayMemoryPool is a shared pool so Dispose() would be a nop even if there were native resources to dispose.
}
}
50 changes: 50 additions & 0 deletions src/System.Memory/src/System/Buffers/MemoryPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace System.Buffers
{
/// <summary>
/// Represents a pool of memory blocks.
/// </summary>
public abstract class MemoryPool<T> : IDisposable
{
private static readonly MemoryPool<T> s_shared = new ArrayMemoryPool<T>();

/// <summary>
/// Returns a singleton instance of a MemoryPool based on arrays.
/// </summary>
public static MemoryPool<T> Shared => s_shared;

/// <summary>
/// Returns a memory block capable of holding at least <paramref name="minBufferSize" /> elements of T.
/// </summary>
/// <param name="minBufferSize">If -1 is passed, this is set to a default value for the pool.</param>
public abstract OwnedMemory<T> Rent(int minBufferSize = -1);

/// <summary>
/// Returns the maximum buffer size supported by this pool.
/// </summary>
public abstract int MaxBufferSize { get; }

/// <summary>
/// Constructs a new instance of a memory pool.
/// </summary>
protected MemoryPool() {}

/// <summary>
/// Frees all resources used by the memory pool.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Frees all resources used by the memory pool.
/// </summary>
/// <param name="disposing"></param>
protected abstract void Dispose(bool disposing);
}
}
10 changes: 10 additions & 0 deletions src/System.Memory/src/System/ThrowHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,18 @@ internal static class ThrowHelper
[MethodImpl(MethodImplOptions.NoInlining)]
private static Exception CreateArgumentOutOfRangeException_SymbolDoesNotFit() { return new ArgumentOutOfRangeException("symbol", SR.Argument_BadFormatSpecifier); }

internal static void ThrowInvalidOperationException() { throw CreateInvalidOperationException(); }
[MethodImpl(MethodImplOptions.NoInlining)]
private static Exception CreateInvalidOperationException() { return new InvalidOperationException(); }

internal static void ThrowInvalidOperationException_OutstandingReferences() { throw CreateInvalidOperationException_OutstandingReferences(); }
[MethodImpl(MethodImplOptions.NoInlining)]
private static Exception CreateInvalidOperationException_OutstandingReferences() { return new InvalidOperationException(SR.OutstandingReferences); }

internal static void ThrowObjectDisposedException_ArrayMemoryPoolBuffer() { throw CreateObjectDisposedException_ArrayMemoryPoolBuffer(); }
[MethodImpl(MethodImplOptions.NoInlining)]
private static Exception CreateObjectDisposedException_ArrayMemoryPoolBuffer() { return new ObjectDisposedException("ArrayMemoryPoolBuffer"); }

internal static void ThrowObjectDisposedException_MemoryDisposed() { throw CreateObjectDisposedException_MemoryDisposed(); }
[MethodImpl(MethodImplOptions.NoInlining)]
private static Exception CreateObjectDisposedException_MemoryDisposed() { return new ObjectDisposedException("OwnedMemory<T>", SR.MemoryDisposed); }
Expand Down Expand Up @@ -106,6 +114,8 @@ internal enum ExceptionArgument
text,
obj,
ownedMemory,
minimumBufferSize,
byteOffset,
pointer,
comparable,
comparer
Expand Down
Loading

0 comments on commit a398684

Please sign in to comment.