Browse Source

Merge pull request #1756 from SixLabors/af/fix-1755

Fix ManagedBufferBase pinning behavior
pull/1771/head
James Jackson-South 5 years ago
committed by GitHub
parent
commit
2b85b553f3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      src/ImageSharp/Memory/Allocators/Internals/ManagedBufferBase.cs
  2. 17
      tests/ImageSharp.Tests/Memory/Allocators/ArrayPoolMemoryAllocatorTests.cs
  3. 20
      tests/ImageSharp.Tests/Memory/Allocators/SimpleGcMemoryAllocatorTests.cs

6
src/ImageSharp/Memory/Allocators/Internals/ManagedBufferBase.cs

@ -24,7 +24,9 @@ namespace SixLabors.ImageSharp.Memory.Internals
}
void* ptr = (void*)this.pinHandle.AddrOfPinnedObject();
return new MemoryHandle(ptr, this.pinHandle);
// We should only pass pinnable:this, when GCHandle lifetime is managed by the MemoryManager<T> instance.
return new MemoryHandle(ptr, pinnable: this);
}
/// <inheritdoc />
@ -42,4 +44,4 @@ namespace SixLabors.ImageSharp.Memory.Internals
/// <returns>The pinnable <see cref="object"/>.</returns>
protected abstract object GetPinnableObject();
}
}
}

17
tests/ImageSharp.Tests/Memory/Allocators/ArrayPoolMemoryAllocatorTests.cs

@ -114,6 +114,23 @@ namespace SixLabors.ImageSharp.Tests.Memory.Allocators
}
}
[Fact]
public unsafe void Allocate_MemoryIsPinnableMultipleTimes()
{
ArrayPoolMemoryAllocator allocator = this.LocalFixture.MemoryAllocator;
using IMemoryOwner<byte> memoryOwner = allocator.Allocate<byte>(100);
using (MemoryHandle pin = memoryOwner.Memory.Pin())
{
Assert.NotEqual(IntPtr.Zero, (IntPtr)pin.Pointer);
}
using (MemoryHandle pin = memoryOwner.Memory.Pin())
{
Assert.NotEqual(IntPtr.Zero, (IntPtr)pin.Pointer);
}
}
[Theory]
[InlineData(false)]
[InlineData(true)]

20
tests/ImageSharp.Tests/Memory/Allocators/SimpleGcMemoryAllocatorTests.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
using Xunit;
@ -36,9 +37,26 @@ namespace SixLabors.ImageSharp.Tests.Memory.Allocators
Assert.Equal("length", ex.ParamName);
}
[Fact]
public unsafe void Allocate_MemoryIsPinnableMultipleTimes()
{
SimpleGcMemoryAllocator allocator = this.MemoryAllocator;
using IMemoryOwner<byte> memoryOwner = allocator.Allocate<byte>(100);
using (MemoryHandle pin = memoryOwner.Memory.Pin())
{
Assert.NotEqual(IntPtr.Zero, (IntPtr)pin.Pointer);
}
using (MemoryHandle pin = memoryOwner.Memory.Pin())
{
Assert.NotEqual(IntPtr.Zero, (IntPtr)pin.Pointer);
}
}
[StructLayout(LayoutKind.Explicit, Size = 512)]
private struct BigStruct
{
}
}
}
}

Loading…
Cancel
Save