Browse Source

Remove nullable disable from Memory.Allocators

#2231
pull/2327/head
Stefan Nikolei 4 years ago
parent
commit
e70e71b16c
  1. 11
      src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs
  2. 2
      src/ImageSharp/Memory/Allocators/Internals/ManagedBufferBase.cs
  3. 3
      src/ImageSharp/Memory/Allocators/Internals/RefCountedMemoryLifetimeGuard.cs
  4. 6
      src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs
  5. 7
      src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs
  6. 11
      src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs
  7. 2
      src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs
  8. 2
      src/ImageSharp/Memory/Buffer2DExtensions.cs
  9. 4
      src/ImageSharp/Memory/Buffer2D{T}.cs
  10. 2
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs
  11. 2
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupSpanCache.cs
  12. 6
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs
  13. 2
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs
  14. 14
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs
  15. 8
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs

11
src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs

@ -1,6 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
#nullable disable
// Port of BCL internal utility: // Port of BCL internal utility:
// https://github.com/dotnet/runtime/blob/57bfe474518ab5b7cfe6bf7424a79ce3af9d6657/src/libraries/System.Private.CoreLib/src/System/Gen2GcCallback.cs // https://github.com/dotnet/runtime/blob/57bfe474518ab5b7cfe6bf7424a79ce3af9d6657/src/libraries/System.Private.CoreLib/src/System/Gen2GcCallback.cs
@ -15,8 +14,8 @@ namespace SixLabors.ImageSharp.Memory.Internals;
/// </summary> /// </summary>
internal sealed class Gen2GcCallback : CriticalFinalizerObject internal sealed class Gen2GcCallback : CriticalFinalizerObject
{ {
private readonly Func<bool> callback0; private readonly Func<bool>? callback0;
private readonly Func<object, bool> callback1; private readonly Func<object, bool>? callback1;
private GCHandle weakTargetObj; private GCHandle weakTargetObj;
private Gen2GcCallback(Func<bool> callback) => this.callback0 = callback; private Gen2GcCallback(Func<bool> callback) => this.callback0 = callback;
@ -32,7 +31,7 @@ internal sealed class Gen2GcCallback : CriticalFinalizerObject
if (this.weakTargetObj.IsAllocated) if (this.weakTargetObj.IsAllocated)
{ {
// Check to see if the target object is still alive. // Check to see if the target object is still alive.
object targetObj = this.weakTargetObj.Target; object? targetObj = this.weakTargetObj.Target;
if (targetObj == null) if (targetObj == null)
{ {
// The target object is dead, so this callback object is no longer needed. // The target object is dead, so this callback object is no longer needed.
@ -43,7 +42,7 @@ internal sealed class Gen2GcCallback : CriticalFinalizerObject
// Execute the callback method. // Execute the callback method.
try try
{ {
if (!this.callback1(targetObj)) if (this.callback1 is not null && !this.callback1(targetObj))
{ {
// If the callback returns false, this callback object is no longer needed. // If the callback returns false, this callback object is no longer needed.
this.weakTargetObj.Free(); this.weakTargetObj.Free();
@ -64,7 +63,7 @@ internal sealed class Gen2GcCallback : CriticalFinalizerObject
// Execute the callback method. // Execute the callback method.
try try
{ {
if (!this.callback0()) if (this.callback0 is not null && !this.callback0())
{ {
// If the callback returns false, this callback object is no longer needed. // If the callback returns false, this callback object is no longer needed.
return; return;

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

@ -43,5 +43,5 @@ internal abstract class ManagedBufferBase<T> : MemoryManager<T>
/// Gets the object that should be pinned. /// Gets the object that should be pinned.
/// </summary> /// </summary>
/// <returns>The pinnable <see cref="object"/>.</returns> /// <returns>The pinnable <see cref="object"/>.</returns>
protected abstract object GetPinnableObject(); protected abstract object? GetPinnableObject();
} }

3
src/ImageSharp/Memory/Allocators/Internals/RefCountedMemoryLifetimeGuard.cs

@ -1,6 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
#nullable disable
using SixLabors.ImageSharp.Diagnostics; using SixLabors.ImageSharp.Diagnostics;
@ -15,7 +14,7 @@ internal abstract class RefCountedMemoryLifetimeGuard : IDisposable
private int refCount = 1; private int refCount = 1;
private int disposed; private int disposed;
private int released; private int released;
private string allocationStackTrace; private string? allocationStackTrace;
protected RefCountedMemoryLifetimeGuard() protected RefCountedMemoryLifetimeGuard()
{ {

6
src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs

@ -1,6 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
#nullable disable
using System.Buffers; using System.Buffers;
using System.Diagnostics; using System.Diagnostics;
@ -22,7 +21,7 @@ internal class SharedArrayPoolBuffer<T> : ManagedBufferBase<T>, IRefCounted
this.lifetimeGuard = new LifetimeGuard(this.Array); this.lifetimeGuard = new LifetimeGuard(this.Array);
} }
public byte[] Array { get; private set; } public byte[]? Array { get; private set; }
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
@ -41,7 +40,7 @@ internal class SharedArrayPoolBuffer<T> : ManagedBufferBase<T>, IRefCounted
return MemoryMarshal.Cast<byte, T>(this.Array.AsSpan(0, this.lengthInBytes)); return MemoryMarshal.Cast<byte, T>(this.Array.AsSpan(0, this.lengthInBytes));
} }
protected override object GetPinnableObject() => this.Array; protected override object? GetPinnableObject() => this.Array;
public void AddRef() public void AddRef()
{ {
@ -74,7 +73,6 @@ internal class SharedArrayPoolBuffer<T> : ManagedBufferBase<T>, IRefCounted
// meaning likely a different bucket than it was rented from, // meaning likely a different bucket than it was rented from,
// but this is PROBABLY better than not returning the arrays at all. // but this is PROBABLY better than not returning the arrays at all.
ArrayPool<byte>.Shared.Return(this.array); ArrayPool<byte>.Shared.Return(this.array);
this.array = null;
} }
} }
} }

7
src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs

@ -1,6 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
#nullable disable
using System.Diagnostics; using System.Diagnostics;
@ -13,7 +12,7 @@ internal partial class UniformUnmanagedMemoryPool : System.Runtime.ConstrainedEx
{ {
private static int minTrimPeriodMilliseconds = int.MaxValue; private static int minTrimPeriodMilliseconds = int.MaxValue;
private static readonly List<WeakReference<UniformUnmanagedMemoryPool>> AllPools = new(); private static readonly List<WeakReference<UniformUnmanagedMemoryPool>> AllPools = new();
private static Timer trimTimer; private static Timer? trimTimer;
private static readonly Stopwatch Stopwatch = Stopwatch.StartNew(); private static readonly Stopwatch Stopwatch = Stopwatch.StartNew();
@ -97,7 +96,7 @@ internal partial class UniformUnmanagedMemoryPool : System.Runtime.ConstrainedEx
/// <summary> /// <summary>
/// Rent <paramref name="bufferCount"/> buffers or return 'null' if the pool is full. /// Rent <paramref name="bufferCount"/> buffers or return 'null' if the pool is full.
/// </summary> /// </summary>
public UnmanagedMemoryHandle[] Rent(int bufferCount) public UnmanagedMemoryHandle[]? Rent(int bufferCount)
{ {
UnmanagedMemoryHandle[] buffersLocal = this.buffers; UnmanagedMemoryHandle[] buffersLocal = this.buffers;
@ -248,7 +247,7 @@ internal partial class UniformUnmanagedMemoryPool : System.Runtime.ConstrainedEx
foreach (WeakReference<UniformUnmanagedMemoryPool> weakPoolRef in AllPools) foreach (WeakReference<UniformUnmanagedMemoryPool> weakPoolRef in AllPools)
{ {
if (weakPoolRef.TryGetTarget(out UniformUnmanagedMemoryPool pool)) if (weakPoolRef.TryGetTarget(out UniformUnmanagedMemoryPool? pool))
{ {
pool.Trim(); pool.Trim();
} }

11
src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs

@ -1,6 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
#nullable disable
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -20,7 +19,7 @@ internal struct UnmanagedMemoryHandle : IEquatable<UnmanagedMemoryHandle>
private static long totalOomRetries; private static long totalOomRetries;
// A Monitor to wait/signal when we are low on memory. // A Monitor to wait/signal when we are low on memory.
private static object lowMemoryMonitor; private static object? lowMemoryMonitor;
public static readonly UnmanagedMemoryHandle NullHandle; public static readonly UnmanagedMemoryHandle NullHandle;
@ -114,9 +113,9 @@ internal struct UnmanagedMemoryHandle : IEquatable<UnmanagedMemoryHandle>
if (Volatile.Read(ref lowMemoryMonitor) != null) if (Volatile.Read(ref lowMemoryMonitor) != null)
{ {
// We are low on memory. Signal all threads waiting in AllocateHandle(). // We are low on memory. Signal all threads waiting in AllocateHandle().
Monitor.Enter(lowMemoryMonitor); Monitor.Enter(lowMemoryMonitor!);
Monitor.PulseAll(lowMemoryMonitor); Monitor.PulseAll(lowMemoryMonitor!);
Monitor.Exit(lowMemoryMonitor); Monitor.Exit(lowMemoryMonitor!);
} }
this.lengthInBytes = 0; this.lengthInBytes = 0;
@ -124,7 +123,7 @@ internal struct UnmanagedMemoryHandle : IEquatable<UnmanagedMemoryHandle>
public bool Equals(UnmanagedMemoryHandle other) => this.handle.Equals(other.handle); public bool Equals(UnmanagedMemoryHandle other) => this.handle.Equals(other.handle);
public override bool Equals(object obj) => obj is UnmanagedMemoryHandle other && this.Equals(other); public override bool Equals(object? obj) => obj is UnmanagedMemoryHandle other && this.Equals(other);
public override int GetHashCode() => this.handle.GetHashCode(); public override int GetHashCode() => this.handle.GetHashCode();
} }

2
src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs

@ -135,7 +135,7 @@ internal sealed class UniformUnmanagedMemoryPoolMemoryAllocator : MemoryAllocato
} }
// Attempt to rent the whole group from the pool, allocate a group of unmanaged buffers if the attempt fails: // Attempt to rent the whole group from the pool, allocate a group of unmanaged buffers if the attempt fails:
if (MemoryGroup<T>.TryAllocate(this.pool, totalLength, bufferAlignment, options, out MemoryGroup<T> poolGroup)) if (MemoryGroup<T>.TryAllocate(this.pool, totalLength, bufferAlignment, options, out MemoryGroup<T>? poolGroup))
{ {
return poolGroup; return poolGroup;
} }

2
src/ImageSharp/Memory/Buffer2DExtensions.cs

@ -22,7 +22,7 @@ public static class Buffer2DExtensions
where T : struct where T : struct
{ {
Guard.NotNull(buffer, nameof(buffer)); Guard.NotNull(buffer, nameof(buffer));
return buffer.FastMemoryGroup.View; return buffer.FastMemoryGroup.View!;
} }
/// <summary> /// <summary>

4
src/ImageSharp/Memory/Buffer2D{T}.cs

@ -43,7 +43,7 @@ public sealed class Buffer2D<T> : IDisposable
/// Gets the backing <see cref="IMemoryGroup{T}"/>. /// Gets the backing <see cref="IMemoryGroup{T}"/>.
/// </summary> /// </summary>
/// <returns>The MemoryGroup.</returns> /// <returns>The MemoryGroup.</returns>
public IMemoryGroup<T> MemoryGroup => this.FastMemoryGroup.View; public IMemoryGroup<T>? MemoryGroup => this.FastMemoryGroup.View;
/// <summary> /// <summary>
/// Gets the backing <see cref="MemoryGroup{T}"/> without the view abstraction. /// Gets the backing <see cref="MemoryGroup{T}"/> without the view abstraction.
@ -138,7 +138,7 @@ public sealed class Buffer2D<T> : IDisposable
{ {
DebugGuard.MustBeGreaterThanOrEqualTo(y, 0, nameof(y)); DebugGuard.MustBeGreaterThanOrEqualTo(y, 0, nameof(y));
DebugGuard.MustBeLessThan(y, this.Height, nameof(y)); DebugGuard.MustBeLessThan(y, this.Height, nameof(y));
return this.FastMemoryGroup.View.GetBoundedMemorySlice(y * (long)this.Width, this.Width); return this.FastMemoryGroup.View!.GetBoundedMemorySlice(y * (long)this.Width, this.Width);
} }
/// <summary> /// <summary>

2
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs

@ -106,7 +106,7 @@ internal static class MemoryGroupExtensions
} }
} }
internal static void CopyTo<T>(this IMemoryGroup<T> source, IMemoryGroup<T> target) internal static void CopyTo<T>(this IMemoryGroup<T>? source, IMemoryGroup<T>? target)
where T : struct where T : struct
{ {
Guard.NotNull(source, nameof(source)); Guard.NotNull(source, nameof(source));

2
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupSpanCache.cs

@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Memory;
internal unsafe struct MemoryGroupSpanCache internal unsafe struct MemoryGroupSpanCache
{ {
public SpanCacheMode Mode; public SpanCacheMode Mode;
public byte[] SingleArray; public byte[]? SingleArray;
public void* SinglePointer; public void* SinglePointer;
public void*[] MultiPointer; public void*[] MultiPointer;

6
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs

@ -1,9 +1,9 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
#nullable disable
using System.Buffers; using System.Buffers;
using System.Collections; using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Memory;
@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Memory;
internal class MemoryGroupView<T> : IMemoryGroup<T> internal class MemoryGroupView<T> : IMemoryGroup<T>
where T : struct where T : struct
{ {
private MemoryGroup<T> owner; private MemoryGroup<T>? owner;
private readonly MemoryOwnerWrapper[] memoryWrappers; private readonly MemoryOwnerWrapper[] memoryWrappers;
public MemoryGroupView(MemoryGroup<T> owner) public MemoryGroupView(MemoryGroup<T> owner)
@ -63,6 +63,7 @@ internal class MemoryGroupView<T> : IMemoryGroup<T>
} }
} }
[MemberNotNullWhen(true, nameof(owner))]
public bool IsValid => this.owner != null; public bool IsValid => this.owner != null;
public Memory<T> this[int index] public Memory<T> this[int index]
@ -99,6 +100,7 @@ internal class MemoryGroupView<T> : IMemoryGroup<T>
this.owner = null; this.owner = null;
} }
[MemberNotNull(nameof(owner))]
private void EnsureIsValid() private void EnsureIsValid()
{ {
if (!this.IsValid) if (!this.IsValid)

2
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs

@ -48,6 +48,6 @@ internal abstract partial class MemoryGroup<T>
return ((IList<Memory<T>>)this.source).GetEnumerator(); return ((IList<Memory<T>>)this.source).GetEnumerator();
} }
public override void Dispose() => this.View.Invalidate(); public override void Dispose() => this.View?.Invalidate();
} }
} }

14
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs

@ -1,8 +1,8 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
#nullable disable
using System.Buffers; using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory.Internals; using SixLabors.ImageSharp.Memory.Internals;
@ -15,8 +15,8 @@ internal abstract partial class MemoryGroup<T>
/// </summary> /// </summary>
public sealed class Owned : MemoryGroup<T>, IEnumerable<Memory<T>> public sealed class Owned : MemoryGroup<T>, IEnumerable<Memory<T>>
{ {
private IMemoryOwner<T>[] memoryOwners; private IMemoryOwner<T>[]? memoryOwners;
private RefCountedMemoryLifetimeGuard groupLifetimeGuard; private RefCountedMemoryLifetimeGuard? groupLifetimeGuard;
public Owned(IMemoryOwner<T>[] memoryOwners, int bufferLength, long totalLength, bool swappable) public Owned(IMemoryOwner<T>[] memoryOwners, int bufferLength, long totalLength, bool swappable)
: base(bufferLength, totalLength) : base(bufferLength, totalLength)
@ -123,7 +123,7 @@ internal abstract partial class MemoryGroup<T>
public override void RecreateViewAfterSwap() public override void RecreateViewAfterSwap()
{ {
this.View.Invalidate(); this.View?.Invalidate();
this.View = new MemoryGroupView<T>(this); this.View = new MemoryGroupView<T>(this);
} }
@ -141,7 +141,7 @@ internal abstract partial class MemoryGroup<T>
return; return;
} }
this.View.Invalidate(); this.View?.Invalidate();
if (this.groupLifetimeGuard != null) if (this.groupLifetimeGuard != null)
{ {
@ -149,7 +149,7 @@ internal abstract partial class MemoryGroup<T>
} }
else else
{ {
foreach (IMemoryOwner<T> memoryOwner in this.memoryOwners) foreach (IMemoryOwner<T> memoryOwner in this.memoryOwners!)
{ {
memoryOwner.Dispose(); memoryOwner.Dispose();
} }
@ -161,6 +161,7 @@ internal abstract partial class MemoryGroup<T>
} }
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
[MemberNotNull(nameof(memoryOwners))]
private void EnsureNotDisposed() private void EnsureNotDisposed()
{ {
if (this.memoryOwners is null) if (this.memoryOwners is null)
@ -170,6 +171,7 @@ internal abstract partial class MemoryGroup<T>
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
[DoesNotReturn]
private static void ThrowObjectDisposedException() => throw new ObjectDisposedException(nameof(MemoryGroup<T>)); private static void ThrowObjectDisposedException() => throw new ObjectDisposedException(nameof(MemoryGroup<T>));
// When the MemoryGroup points to multiple buffers via `groupLifetimeGuard`, // When the MemoryGroup points to multiple buffers via `groupLifetimeGuard`,

8
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs

@ -1,9 +1,9 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
#nullable disable
using System.Buffers; using System.Buffers;
using System.Collections; using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory.Internals; using SixLabors.ImageSharp.Memory.Internals;
@ -41,7 +41,7 @@ internal abstract partial class MemoryGroup<T> : IMemoryGroup<T>, IDisposable
/// <inheritdoc /> /// <inheritdoc />
public bool IsValid { get; private set; } = true; public bool IsValid { get; private set; } = true;
public MemoryGroupView<T> View { get; private set; } public MemoryGroupView<T>? View { get; private set; }
/// <inheritdoc /> /// <inheritdoc />
public abstract Memory<T> this[int index] { get; } public abstract Memory<T> this[int index] { get; }
@ -150,7 +150,7 @@ internal abstract partial class MemoryGroup<T> : IMemoryGroup<T>, IDisposable
long totalLengthInElements, long totalLengthInElements,
int bufferAlignmentInElements, int bufferAlignmentInElements,
AllocationOptions options, AllocationOptions options,
out MemoryGroup<T> memoryGroup) [NotNullWhen(true)] out MemoryGroup<T>? memoryGroup)
{ {
Guard.NotNull(pool, nameof(pool)); Guard.NotNull(pool, nameof(pool));
Guard.MustBeGreaterThanOrEqualTo(totalLengthInElements, 0, nameof(totalLengthInElements)); Guard.MustBeGreaterThanOrEqualTo(totalLengthInElements, 0, nameof(totalLengthInElements));
@ -188,7 +188,7 @@ internal abstract partial class MemoryGroup<T> : IMemoryGroup<T>, IDisposable
bufferCount++; bufferCount++;
} }
UnmanagedMemoryHandle[] arrays = pool.Rent(bufferCount); UnmanagedMemoryHandle[]? arrays = pool.Rent(bufferCount);
if (arrays == null) if (arrays == null)
{ {

Loading…
Cancel
Save