|
|
|
@ -13,7 +13,8 @@ namespace SixLabors.ImageSharp.Tests.Memory |
|
|
|
{ |
|
|
|
internal class TestMemoryAllocator : MemoryAllocator |
|
|
|
{ |
|
|
|
private List<AllocationRequest> allocationLog = new List<AllocationRequest>(); |
|
|
|
private readonly List<AllocationRequest> allocationLog = new List<AllocationRequest>(); |
|
|
|
private readonly List<ReturnRequest> returnLog = new List<ReturnRequest>(); |
|
|
|
|
|
|
|
public TestMemoryAllocator(byte dirtyValue = 42) |
|
|
|
{ |
|
|
|
@ -27,27 +28,29 @@ namespace SixLabors.ImageSharp.Tests.Memory |
|
|
|
|
|
|
|
public int BlockCapacity { get; set; } = int.MaxValue; |
|
|
|
|
|
|
|
public IList<AllocationRequest> AllocationLog => this.allocationLog; |
|
|
|
public IReadOnlyList<AllocationRequest> AllocationLog => this.allocationLog; |
|
|
|
|
|
|
|
public IReadOnlyList<ReturnRequest> ReturnLog => this.returnLog; |
|
|
|
|
|
|
|
protected internal override int GetBlockCapacity() => this.BlockCapacity; |
|
|
|
|
|
|
|
public override IMemoryOwner<T> Allocate<T>(int length, AllocationOptions options = AllocationOptions.None) |
|
|
|
{ |
|
|
|
T[] array = this.AllocateArray<T>(length, options); |
|
|
|
return new BasicArrayBuffer<T>(array, length); |
|
|
|
return new BasicArrayBuffer<T>(array, length, this); |
|
|
|
} |
|
|
|
|
|
|
|
public override IManagedByteBuffer AllocateManagedByteBuffer(int length, AllocationOptions options = AllocationOptions.None) |
|
|
|
{ |
|
|
|
byte[] array = this.AllocateArray<byte>(length, options); |
|
|
|
return new ManagedByteBuffer(array); |
|
|
|
return new ManagedByteBuffer(array, this); |
|
|
|
} |
|
|
|
|
|
|
|
private T[] AllocateArray<T>(int length, AllocationOptions options) |
|
|
|
where T : struct |
|
|
|
{ |
|
|
|
this.allocationLog.Add(AllocationRequest.Create<T>(options, length)); |
|
|
|
var array = new T[length + 42]; |
|
|
|
this.allocationLog.Add(AllocationRequest.Create<T>(options, length, array)); |
|
|
|
|
|
|
|
if (options == AllocationOptions.None) |
|
|
|
{ |
|
|
|
@ -58,25 +61,32 @@ namespace SixLabors.ImageSharp.Tests.Memory |
|
|
|
return array; |
|
|
|
} |
|
|
|
|
|
|
|
private void Return<T>(BasicArrayBuffer<T> buffer) |
|
|
|
where T : struct |
|
|
|
{ |
|
|
|
this.returnLog.Add(new ReturnRequest(buffer.Array.GetHashCode())); |
|
|
|
} |
|
|
|
|
|
|
|
public struct AllocationRequest |
|
|
|
{ |
|
|
|
private AllocationRequest(Type elementType, AllocationOptions allocationOptions, int length, int lengthInBytes) |
|
|
|
private AllocationRequest(Type elementType, AllocationOptions allocationOptions, int length, int lengthInBytes, int hashCodeOfBuffer) |
|
|
|
{ |
|
|
|
this.ElementType = elementType; |
|
|
|
this.AllocationOptions = allocationOptions; |
|
|
|
this.Length = length; |
|
|
|
this.LengthInBytes = lengthInBytes; |
|
|
|
this.HashCodeOfBuffer = hashCodeOfBuffer; |
|
|
|
|
|
|
|
if (elementType == typeof(Vector4)) |
|
|
|
{ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public static AllocationRequest Create<T>(AllocationOptions allocationOptions, int length) |
|
|
|
public static AllocationRequest Create<T>(AllocationOptions allocationOptions, int length, T[] buffer) |
|
|
|
{ |
|
|
|
Type type = typeof(T); |
|
|
|
int elementSize = Marshal.SizeOf(type); |
|
|
|
return new AllocationRequest(type, allocationOptions, length, length * elementSize); |
|
|
|
return new AllocationRequest(type, allocationOptions, length, length * elementSize, buffer.GetHashCode()); |
|
|
|
} |
|
|
|
|
|
|
|
public Type ElementType { get; } |
|
|
|
@ -86,6 +96,18 @@ namespace SixLabors.ImageSharp.Tests.Memory |
|
|
|
public int Length { get; } |
|
|
|
|
|
|
|
public int LengthInBytes { get; } |
|
|
|
|
|
|
|
public int HashCodeOfBuffer { get; } |
|
|
|
} |
|
|
|
|
|
|
|
public struct ReturnRequest |
|
|
|
{ |
|
|
|
public ReturnRequest(int hashCodeOfBuffer) |
|
|
|
{ |
|
|
|
this.HashCodeOfBuffer = hashCodeOfBuffer; |
|
|
|
} |
|
|
|
|
|
|
|
public int HashCodeOfBuffer { get; } |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -94,36 +116,29 @@ namespace SixLabors.ImageSharp.Tests.Memory |
|
|
|
private class BasicArrayBuffer<T> : MemoryManager<T> |
|
|
|
where T : struct |
|
|
|
{ |
|
|
|
private readonly TestMemoryAllocator allocator; |
|
|
|
private GCHandle pinHandle; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="BasicArrayBuffer{T}"/> class
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="array">The array</param>
|
|
|
|
/// <param name="length">The length of the buffer</param>
|
|
|
|
public BasicArrayBuffer(T[] array, int length) |
|
|
|
public BasicArrayBuffer(T[] array, int length, TestMemoryAllocator allocator) |
|
|
|
{ |
|
|
|
this.allocator = allocator; |
|
|
|
DebugGuard.MustBeLessThanOrEqualTo(length, array.Length, nameof(length)); |
|
|
|
this.Array = array; |
|
|
|
this.Length = length; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="BasicArrayBuffer{T}"/> class
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="array">The array</param>
|
|
|
|
public BasicArrayBuffer(T[] array) |
|
|
|
: this(array, array.Length) |
|
|
|
public BasicArrayBuffer(T[] array, TestMemoryAllocator allocator) |
|
|
|
: this(array, array.Length, allocator) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the array
|
|
|
|
/// Gets the array.
|
|
|
|
/// </summary>
|
|
|
|
public T[] Array { get; } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the length
|
|
|
|
/// Gets the length.
|
|
|
|
/// </summary>
|
|
|
|
public int Length { get; } |
|
|
|
|
|
|
|
@ -149,13 +164,17 @@ namespace SixLabors.ImageSharp.Tests.Memory |
|
|
|
/// <inheritdoc />
|
|
|
|
protected override void Dispose(bool disposing) |
|
|
|
{ |
|
|
|
if (disposing) |
|
|
|
{ |
|
|
|
this.allocator.Return(this); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private class ManagedByteBuffer : BasicArrayBuffer<byte>, IManagedByteBuffer |
|
|
|
{ |
|
|
|
public ManagedByteBuffer(byte[] array) |
|
|
|
: base(array) |
|
|
|
public ManagedByteBuffer(byte[] array, TestMemoryAllocator allocator) |
|
|
|
: base(array, allocator) |
|
|
|
{ |
|
|
|
} |
|
|
|
} |
|
|
|
|