Adding back the byteOffset to OwnedMemory Pin (#2067)
This commit is contained in:
Родитель
3cb38284f2
Коммит
1183c2a37f
|
@ -1 +1 @@
|
|||
2.2.0-preview1-008003
|
||||
2.1.300-preview2-008018
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.1.0-preview1-26122-01
|
||||
2.1.0-preview2-26124-05
|
|
@ -2,7 +2,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.2020
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MultiSegmentBytesReaderNumbers", "MultiSegmentBytesReaderNumbers", "{5E7EB061-B9BC-4DA2-B5E5-859AA7C67695}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5E7EB061-B9BC-4DA2-B5E5-859AA7C67695}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
global.json = global.json
|
||||
NuGet.Config = NuGet.Config
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Buffers.Native;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace System.Buffers.Native
|
||||
{
|
||||
|
@ -41,10 +42,11 @@ namespace System.Buffers.Native
|
|||
return false;
|
||||
}
|
||||
|
||||
public override MemoryHandle Pin()
|
||||
public override MemoryHandle Pin(int byteOffset = 0)
|
||||
{
|
||||
Retain();
|
||||
return new MemoryHandle(this, _pointer.ToPointer());
|
||||
if (byteOffset < 0 || byteOffset > _length) throw new ArgumentOutOfRangeException(nameof(byteOffset));
|
||||
return new MemoryHandle(this, Unsafe.Add<byte>(_pointer.ToPointer(), byteOffset));
|
||||
}
|
||||
|
||||
private readonly NativeMemoryPool _pool;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace System.Buffers.Native
|
||||
|
@ -36,12 +37,13 @@ namespace System.Buffers.Native
|
|||
_pointer = IntPtr.Zero;
|
||||
}
|
||||
|
||||
public override MemoryHandle Pin()
|
||||
public override MemoryHandle Pin(int byteOffset = 0)
|
||||
{
|
||||
Retain();
|
||||
if (byteOffset < 0 || byteOffset > _length) throw new ArgumentOutOfRangeException(nameof(byteOffset));
|
||||
unsafe
|
||||
{
|
||||
return new MemoryHandle(this, _pointer.ToPointer());
|
||||
return new MemoryHandle(this, Unsafe.Add<byte>(_pointer.ToPointer(), byteOffset));
|
||||
}
|
||||
}
|
||||
protected override bool TryGetArray(out ArraySegment<byte> arraySegment)
|
||||
|
|
|
@ -59,9 +59,10 @@ namespace System.Buffers.Native
|
|||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
public unsafe override MemoryHandle Pin()
|
||||
public unsafe override MemoryHandle Pin(int byteOffset = 0)
|
||||
{
|
||||
return new MemoryHandle(this, _pointer.ToPointer());
|
||||
if (byteOffset < 0 || (byteOffset / Unsafe.SizeOf<T>()) > _array.Length) throw new ArgumentOutOfRangeException(nameof(byteOffset));
|
||||
return new MemoryHandle(this, Unsafe.Add<byte>(_pointer.ToPointer(), byteOffset));
|
||||
}
|
||||
|
||||
protected override bool TryGetArray(out ArraySegment<T> arraySegment)
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace System.Buffers
|
|||
|
||||
public OwnedArray(T[] array)
|
||||
{
|
||||
if (array == null) ThrowArgumentNullException(nameof(array));
|
||||
if (array == null) ThrowArgumentNullException(nameof(array));
|
||||
_array = array;
|
||||
}
|
||||
|
||||
|
@ -37,13 +37,15 @@ namespace System.Buffers
|
|||
}
|
||||
}
|
||||
|
||||
public override MemoryHandle Pin()
|
||||
public override MemoryHandle Pin(int byteOffset = 0)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
Retain();
|
||||
if (byteOffset < 0 || (byteOffset / Unsafe.SizeOf<T>()) > _array.Length) throw new ArgumentOutOfRangeException(nameof(byteOffset));
|
||||
var handle = GCHandle.Alloc(_array, GCHandleType.Pinned);
|
||||
return new MemoryHandle(this, (void*)handle.AddrOfPinnedObject(), handle);
|
||||
void* pointer = Unsafe.Add<byte>((void*)handle.AddrOfPinnedObject(), byteOffset);
|
||||
return new MemoryHandle(this, pointer, handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +70,7 @@ namespace System.Buffers
|
|||
public override bool Release()
|
||||
{
|
||||
int newRefCount = Interlocked.Decrement(ref _referenceCount);
|
||||
if (newRefCount < 0) ThrowInvalidOperationException();
|
||||
if (newRefCount < 0) ThrowInvalidOperationException();
|
||||
if (newRefCount == 0)
|
||||
{
|
||||
OnNoReferences();
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace System.Buffers.Internal
|
|||
T[] _array;
|
||||
bool _disposed;
|
||||
int _referenceCount;
|
||||
|
||||
|
||||
public ArrayPoolMemory(int size)
|
||||
{
|
||||
_array = ArrayPool<T>.Shared.Rent(size);
|
||||
|
@ -57,7 +57,8 @@ namespace System.Buffers.Internal
|
|||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
var array = Interlocked.Exchange(ref _array, null);
|
||||
if (array != null) {
|
||||
if (array != null)
|
||||
{
|
||||
_disposed = true;
|
||||
ArrayPool<T>.Shared.Return(array);
|
||||
}
|
||||
|
@ -70,13 +71,15 @@ namespace System.Buffers.Internal
|
|||
return true;
|
||||
}
|
||||
|
||||
public override MemoryHandle Pin()
|
||||
public override MemoryHandle Pin(int byteOffset = 0)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
Retain(); // this checks IsDisposed
|
||||
if (byteOffset < 0 || (byteOffset / Unsafe.SizeOf<T>()) > _array.Length) throw new ArgumentOutOfRangeException(nameof(byteOffset));
|
||||
var handle = GCHandle.Alloc(_array, GCHandleType.Pinned);
|
||||
return new MemoryHandle(this, (void*)handle.AddrOfPinnedObject(), handle);
|
||||
void* pointer = Unsafe.Add<byte>((void*)handle.AddrOfPinnedObject(), byteOffset);
|
||||
return new MemoryHandle(this, pointer, handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +93,7 @@ namespace System.Buffers.Internal
|
|||
{
|
||||
int newRefCount = Interlocked.Decrement(ref _referenceCount);
|
||||
if (newRefCount < 0) throw new InvalidOperationException();
|
||||
if (newRefCount == 0)
|
||||
if (newRefCount == 0)
|
||||
{
|
||||
Dispose();
|
||||
return false;
|
||||
|
|
|
@ -116,8 +116,8 @@ namespace System.Buffers
|
|||
if (newRefCount < 0) RioPipelinesThrowHelper.ThrowInvalidOperationException(ExceptionResource.ReferenceCountZero);
|
||||
if (newRefCount == 0)
|
||||
{
|
||||
OnZeroReferences();
|
||||
return false;
|
||||
OnZeroReferences();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -134,13 +134,13 @@ namespace System.Buffers
|
|||
return true;
|
||||
}
|
||||
|
||||
public override MemoryHandle Pin()
|
||||
public override MemoryHandle Pin(int byteOffset = 0)
|
||||
{
|
||||
if (IsDisposed) RioPipelinesThrowHelper.ThrowObjectDisposedException(nameof(RioMemoryPoolBlock));
|
||||
Retain();
|
||||
Retain(); // checks IsDisposed
|
||||
if (byteOffset < 0 || byteOffset > _length) RioPipelinesThrowHelper.ThrowArgumentOutOfRangeException(_length, byteOffset);
|
||||
unsafe
|
||||
{
|
||||
return new MemoryHandle(this, (Slab.NativePointer + _offset).ToPointer());
|
||||
return new MemoryHandle(this, (Slab.NativePointer + _offset + byteOffset).ToPointer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,30 @@ using System.Runtime.CompilerServices;
|
|||
namespace System.IO.Pipelines
|
||||
{
|
||||
internal class RioPipelinesThrowHelper
|
||||
{
|
||||
{
|
||||
public static void ThrowArgumentOutOfRangeException(int sourceLength, int offset)
|
||||
{
|
||||
throw GetArgumentOutOfRangeException(sourceLength, offset);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(int sourceLength, int offset)
|
||||
{
|
||||
if ((uint)offset > (uint)sourceLength)
|
||||
{
|
||||
// Offset is negative or less than array length
|
||||
return new ArgumentOutOfRangeException(GetArgumentName(ExceptionArgument.offset));
|
||||
}
|
||||
|
||||
// The third parameter (not passed) length must be out of range
|
||||
return new ArgumentOutOfRangeException(GetArgumentName(ExceptionArgument.length));
|
||||
}
|
||||
|
||||
public static void ThrowInvalidOperationException(ExceptionResource resource, string location = null)
|
||||
{
|
||||
throw GetInvalidOperationException(resource, location);
|
||||
}
|
||||
|
||||
|
||||
public static void ThrowArgumentOutOfRangeException_BufferRequestTooLarge(int maxSize)
|
||||
{
|
||||
throw GetArgumentOutOfRangeException_BufferRequestTooLarge(maxSize);
|
||||
|
@ -28,7 +46,7 @@ namespace System.IO.Pipelines
|
|||
{
|
||||
return new InvalidOperationException(GetResourceString(resource, location));
|
||||
}
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static ArgumentOutOfRangeException GetArgumentOutOfRangeException_BufferRequestTooLarge(int maxSize)
|
||||
{
|
||||
|
|
|
@ -116,8 +116,8 @@ namespace System.Buffers
|
|||
if (newRefCount < 0) PipelinesThrowHelper.ThrowInvalidOperationException(ExceptionResource.ReferenceCountZero);
|
||||
if (newRefCount == 0)
|
||||
{
|
||||
OnZeroReferences();
|
||||
return false;
|
||||
OnZeroReferences();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -134,13 +134,13 @@ namespace System.Buffers
|
|||
return true;
|
||||
}
|
||||
|
||||
public override MemoryHandle Pin()
|
||||
public override MemoryHandle Pin(int byteOffset = 0)
|
||||
{
|
||||
if (IsDisposed) PipelinesThrowHelper.ThrowObjectDisposedException(nameof(MemoryPoolBlock));
|
||||
Retain();
|
||||
Retain(); // checks IsDisposed
|
||||
if (byteOffset < 0 || byteOffset > _length) PipelinesThrowHelper.ThrowArgumentOutOfRangeException(_length, byteOffset);
|
||||
unsafe
|
||||
{
|
||||
return new MemoryHandle(this, (Slab.NativePointer + _offset).ToPointer());
|
||||
return new MemoryHandle(this, (Slab.NativePointer + _offset + byteOffset).ToPointer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
using System.Buffers.Native;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -12,8 +13,9 @@ namespace System.Buffers.Tests
|
|||
{
|
||||
[Fact]
|
||||
public void SimpleTests()
|
||||
{
|
||||
using(var owned = new OwnedNativeBuffer(1024)) {
|
||||
{
|
||||
using (var owned = new OwnedNativeBuffer(1024))
|
||||
{
|
||||
var span = owned.Span;
|
||||
span[10] = 10;
|
||||
unsafe { Assert.Equal(10, owned.Pointer[10]); }
|
||||
|
@ -28,7 +30,8 @@ namespace System.Buffers.Tests
|
|||
Assert.Equal(10, copy[0]);
|
||||
}
|
||||
|
||||
using (OwnedPinnedBuffer<byte> owned = new byte[1024]) {
|
||||
using (OwnedPinnedBuffer<byte> owned = new byte[1024])
|
||||
{
|
||||
var span = owned.Span;
|
||||
span[10] = 10;
|
||||
Assert.Equal(10, owned.Array[10]);
|
||||
|
@ -57,33 +60,40 @@ namespace System.Buffers.Tests
|
|||
public unsafe void PinnedArrayMemoryLifetime()
|
||||
{
|
||||
var bytes = new byte[1024];
|
||||
fixed (byte* pBytes = bytes) {
|
||||
fixed (byte* pBytes = bytes)
|
||||
{
|
||||
var owner = new OwnedPinnedBuffer<byte>(bytes, pBytes);
|
||||
TestLifetime(owner);
|
||||
TestLifetime(owner);
|
||||
}
|
||||
}
|
||||
|
||||
static void TestLifetime(OwnedMemory<byte> owned)
|
||||
{
|
||||
Memory<byte> copyStoredForLater;
|
||||
try {
|
||||
try
|
||||
{
|
||||
Memory<byte> memory = owned.Memory;
|
||||
Memory<byte> memorySlice = memory.Slice(10);
|
||||
copyStoredForLater = memorySlice;
|
||||
var r = memorySlice.Retain();
|
||||
try {
|
||||
Assert.Throws<InvalidOperationException>(() => { // memory is reserved; premature dispose check fires
|
||||
try
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{ // memory is reserved; premature dispose check fires
|
||||
owned.Dispose();
|
||||
});
|
||||
}
|
||||
finally {
|
||||
finally
|
||||
{
|
||||
r.Dispose(); // release reservation
|
||||
}
|
||||
}
|
||||
finally {
|
||||
finally
|
||||
{
|
||||
owned.Dispose(); // can finish dispose with no exception
|
||||
}
|
||||
Assert.Throws<ObjectDisposedException>(() => {
|
||||
Assert.Throws<ObjectDisposedException>(() =>
|
||||
{
|
||||
// memory is disposed; cannot use copy stored for later
|
||||
var span = copyStoredForLater.Span;
|
||||
});
|
||||
|
@ -110,7 +120,7 @@ namespace System.Buffers.Tests
|
|||
var owned = new CustomBuffer<byte>(255);
|
||||
var memory = owned.Memory;
|
||||
Assert.Equal(0, owned.OnNoRefencesCalledCount);
|
||||
|
||||
|
||||
using (memory.Retain())
|
||||
{
|
||||
Assert.Equal(0, owned.OnNoRefencesCalledCount);
|
||||
|
@ -136,7 +146,8 @@ namespace System.Buffers.Tests
|
|||
memories[i] = owners[i].Memory;
|
||||
}
|
||||
|
||||
var dispose_task = Task.Run(() => {
|
||||
var dispose_task = Task.Run(() =>
|
||||
{
|
||||
for (int i = 0; i < owners.Length; i++)
|
||||
{
|
||||
try
|
||||
|
@ -151,7 +162,8 @@ namespace System.Buffers.Tests
|
|||
}
|
||||
});
|
||||
|
||||
var reserve_task = Task.Run(() => {
|
||||
var reserve_task = Task.Run(() =>
|
||||
{
|
||||
for (int i = owners.Length - 1; i >= 0; i--)
|
||||
{
|
||||
try
|
||||
|
@ -205,13 +217,15 @@ namespace System.Buffers.Tests
|
|||
}
|
||||
}
|
||||
|
||||
public override MemoryHandle Pin()
|
||||
public override MemoryHandle Pin(int byteOffset = 0)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
Retain();
|
||||
if (byteOffset < 0 || (byteOffset / Unsafe.SizeOf<T>()) > _array.Length) throw new ArgumentOutOfRangeException(nameof(byteOffset));
|
||||
var handle = GCHandle.Alloc(_array, GCHandleType.Pinned);
|
||||
return new MemoryHandle(this, (void*)handle.AddrOfPinnedObject(), handle);
|
||||
void* pointer = Unsafe.Add<byte>((void*)handle.AddrOfPinnedObject(), byteOffset);
|
||||
return new MemoryHandle(this, pointer, handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,8 +254,8 @@ namespace System.Buffers.Tests
|
|||
if (newRefCount < 0) throw new InvalidOperationException();
|
||||
if (newRefCount == 0)
|
||||
{
|
||||
_noReferencesCalledCount++;
|
||||
return false;
|
||||
_noReferencesCalledCount++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -283,13 +297,15 @@ namespace System.Buffers.Tests
|
|||
return true;
|
||||
}
|
||||
|
||||
public override MemoryHandle Pin()
|
||||
public override MemoryHandle Pin(int byteOffset = 0)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
Retain();
|
||||
if (byteOffset < 0 || (byteOffset / Unsafe.SizeOf<T>()) > _array.Length) throw new ArgumentOutOfRangeException(nameof(byteOffset));
|
||||
var handle = GCHandle.Alloc(_array, GCHandleType.Pinned);
|
||||
return new MemoryHandle(this, (void*)handle.AddrOfPinnedObject(), handle);
|
||||
void* pointer = Unsafe.Add<byte>((void*)handle.AddrOfPinnedObject(), byteOffset);
|
||||
return new MemoryHandle(this, pointer, handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
|
@ -38,13 +39,15 @@ namespace System.Buffers.Tests
|
|||
}
|
||||
}
|
||||
|
||||
public override MemoryHandle Pin()
|
||||
public override MemoryHandle Pin(int byteOffset = 0)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
Retain();
|
||||
if (byteOffset < 0 || (byteOffset / Unsafe.SizeOf<T>()) > _array.Length) throw new ArgumentOutOfRangeException(nameof(byteOffset));
|
||||
var handle = GCHandle.Alloc(_array, GCHandleType.Pinned);
|
||||
return new MemoryHandle(this, (void*)handle.AddrOfPinnedObject(), handle);
|
||||
void* pointer = Unsafe.Add<byte>((void*)handle.AddrOfPinnedObject(), byteOffset);
|
||||
return new MemoryHandle(this, pointer, handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ namespace System.IO.Pipelines.Tests
|
|||
}
|
||||
}
|
||||
|
||||
public override MemoryHandle Pin()
|
||||
public override MemoryHandle Pin(int byteOffset = 0)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
@ -44,12 +44,14 @@ namespace System.Numerics.Tensors.Tests
|
|||
|
||||
protected override bool IsRetained => refCount > 0;
|
||||
|
||||
public override MemoryHandle Pin()
|
||||
public override MemoryHandle Pin(int byteOffset = 0)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
Retain();
|
||||
return new MemoryHandle(this, (void*)memory);
|
||||
if (byteOffset < 0 || (byteOffset / Marshal.SizeOf<T>()) > length) throw new ArgumentOutOfRangeException(nameof(byteOffset));
|
||||
void* pointer = (void*)((byte*)memory + byteOffset);
|
||||
return new MemoryHandle(this, pointer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<RuntimeFrameworkVersion>2.1.0-preview1-26122-01</RuntimeFrameworkVersion>
|
||||
<RuntimeFrameworkVersion>2.1.0-preview2-26124-05</RuntimeFrameworkVersion>
|
||||
<CoreFxStableVersion>4.3.0</CoreFxStableVersion>
|
||||
<RoslynVersion>2.6.0-beta3-62316-02</RoslynVersion>
|
||||
<SystemMemoryVersion>4.5.0-preview1-26122-01</SystemMemoryVersion>
|
||||
<SystemCompilerServicesUnsafeVersion>4.5.0-preview1-26122-01</SystemCompilerServicesUnsafeVersion>
|
||||
<SystemNumericsVectorsVersion>4.5.0-preview1-26122-01</SystemNumericsVectorsVersion>
|
||||
<SystemMemoryVersion>4.5.0-preview2-26124-02</SystemMemoryVersion>
|
||||
<SystemCompilerServicesUnsafeVersion>4.5.0-preview2-26124-02</SystemCompilerServicesUnsafeVersion>
|
||||
<SystemNumericsVectorsVersion>4.5.0-preview2-26124-02</SystemNumericsVectorsVersion>
|
||||
<LibuvVersion>1.9.1</LibuvVersion>
|
||||
<TestSdkVersion>15.0.0</TestSdkVersion>
|
||||
<XunitVersion>2.2.0</XunitVersion>
|
||||
|
|
Загрузка…
Ссылка в новой задаче