Browse Source

Merge pull request #2327 from stefannikolei/stefannikolei/nullable/memory

Remove nullable disable from Memory.Allocators
pull/2335/head
James Jackson-South 3 years ago
committed by GitHub
parent
commit
84dcd187fe
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs
  2. 3
      src/ImageSharp/Memory/Allocators/Internals/RefCountedMemoryLifetimeGuard.cs
  3. 15
      src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs
  4. 7
      src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs
  5. 11
      src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs
  6. 2
      src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs
  7. 2
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs
  8. 2
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupSpanCache.cs
  9. 6
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs
  10. 10
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs
  11. 8
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs

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

@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable
// Port of BCL internal utility:
// 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>
internal sealed class Gen2GcCallback : CriticalFinalizerObject
{
private readonly Func<bool> callback0;
private readonly Func<object, bool> callback1;
private readonly Func<bool>? callback0;
private readonly Func<object, bool>? callback1;
private GCHandle weakTargetObj;
private Gen2GcCallback(Func<bool> callback) => this.callback0 = callback;
@ -32,7 +31,7 @@ internal sealed class Gen2GcCallback : CriticalFinalizerObject
if (this.weakTargetObj.IsAllocated)
{
// Check to see if the target object is still alive.
object targetObj = this.weakTargetObj.Target;
object? targetObj = this.weakTargetObj.Target;
if (targetObj == null)
{
// 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.
try
{
if (!this.callback1(targetObj))
if (!this.callback1!(targetObj))
{
// If the callback returns false, this callback object is no longer needed.
this.weakTargetObj.Free();
@ -64,7 +63,7 @@ internal sealed class Gen2GcCallback : CriticalFinalizerObject
// Execute the callback method.
try
{
if (!this.callback0())
if (!this.callback0!())
{
// If the callback returns false, this callback object is no longer needed.
return;

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

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

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

@ -1,9 +1,9 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable
using System.Buffers;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -22,7 +22,7 @@ internal class SharedArrayPoolBuffer<T> : ManagedBufferBase<T>, IRefCounted
this.lifetimeGuard = new LifetimeGuard(this.Array);
}
public byte[] Array { get; private set; }
public byte[]? Array { get; private set; }
protected override void Dispose(bool disposing)
{
@ -41,7 +41,11 @@ internal class SharedArrayPoolBuffer<T> : ManagedBufferBase<T>, IRefCounted
return MemoryMarshal.Cast<byte, T>(this.Array.AsSpan(0, this.lengthInBytes));
}
protected override object GetPinnableObject() => this.Array;
protected override object GetPinnableObject()
{
this.CheckDisposed();
return this.Array;
}
public void AddRef()
{
@ -52,6 +56,7 @@ internal class SharedArrayPoolBuffer<T> : ManagedBufferBase<T>, IRefCounted
public void ReleaseRef() => this.lifetimeGuard.ReleaseRef();
[Conditional("DEBUG")]
[MemberNotNull(nameof(Array))]
private void CheckDisposed()
{
if (this.Array == null)
@ -62,7 +67,7 @@ internal class SharedArrayPoolBuffer<T> : ManagedBufferBase<T>, IRefCounted
private sealed class LifetimeGuard : RefCountedMemoryLifetimeGuard
{
private byte[] array;
private byte[]? array;
public LifetimeGuard(byte[] array) => this.array = array;
@ -73,7 +78,7 @@ internal class SharedArrayPoolBuffer<T> : ManagedBufferBase<T>, IRefCounted
// This is not ideal, but subsequent leaks will end up returning arrays to per-cpu buckets,
// meaning likely a different bucket than it was rented from,
// 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.
// Licensed under the Six Labors Split License.
#nullable disable
using System.Diagnostics;
@ -13,7 +12,7 @@ internal partial class UniformUnmanagedMemoryPool : System.Runtime.ConstrainedEx
{
private static int minTrimPeriodMilliseconds = int.MaxValue;
private static readonly List<WeakReference<UniformUnmanagedMemoryPool>> AllPools = new();
private static Timer trimTimer;
private static Timer? trimTimer;
private static readonly Stopwatch Stopwatch = Stopwatch.StartNew();
@ -97,7 +96,7 @@ internal partial class UniformUnmanagedMemoryPool : System.Runtime.ConstrainedEx
/// <summary>
/// Rent <paramref name="bufferCount"/> buffers or return 'null' if the pool is full.
/// </summary>
public UnmanagedMemoryHandle[] Rent(int bufferCount)
public UnmanagedMemoryHandle[]? Rent(int bufferCount)
{
UnmanagedMemoryHandle[] buffersLocal = this.buffers;
@ -248,7 +247,7 @@ internal partial class UniformUnmanagedMemoryPool : System.Runtime.ConstrainedEx
foreach (WeakReference<UniformUnmanagedMemoryPool> weakPoolRef in AllPools)
{
if (weakPoolRef.TryGetTarget(out UniformUnmanagedMemoryPool pool))
if (weakPoolRef.TryGetTarget(out UniformUnmanagedMemoryPool? pool))
{
pool.Trim();
}

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

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

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:
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;
}

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
{
Guard.NotNull(source, nameof(source));

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

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

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

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

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

@ -1,8 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable
using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory.Internals;
@ -15,8 +15,8 @@ internal abstract partial class MemoryGroup<T>
/// </summary>
public sealed class Owned : MemoryGroup<T>, IEnumerable<Memory<T>>
{
private IMemoryOwner<T>[] memoryOwners;
private RefCountedMemoryLifetimeGuard groupLifetimeGuard;
private IMemoryOwner<T>[]? memoryOwners;
private RefCountedMemoryLifetimeGuard? groupLifetimeGuard;
public Owned(IMemoryOwner<T>[] memoryOwners, int bufferLength, long totalLength, bool swappable)
: base(bufferLength, totalLength)
@ -149,7 +149,7 @@ internal abstract partial class MemoryGroup<T>
}
else
{
foreach (IMemoryOwner<T> memoryOwner in this.memoryOwners)
foreach (IMemoryOwner<T> memoryOwner in this.memoryOwners!)
{
memoryOwner.Dispose();
}
@ -161,6 +161,7 @@ internal abstract partial class MemoryGroup<T>
}
[MethodImpl(InliningOptions.ShortMethod)]
[MemberNotNull(nameof(memoryOwners))]
private void EnsureNotDisposed()
{
if (this.memoryOwners is null)
@ -170,6 +171,7 @@ internal abstract partial class MemoryGroup<T>
}
[MethodImpl(MethodImplOptions.NoInlining)]
[DoesNotReturn]
private static void ThrowObjectDisposedException() => throw new ObjectDisposedException(nameof(MemoryGroup<T>));
// 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.
// Licensed under the Six Labors Split License.
#nullable disable
using System.Buffers;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory.Internals;
@ -41,7 +41,7 @@ internal abstract partial class MemoryGroup<T> : IMemoryGroup<T>, IDisposable
/// <inheritdoc />
public bool IsValid { get; private set; } = true;
public MemoryGroupView<T> View { get; private set; }
public MemoryGroupView<T> View { get; private set; } = null!;
/// <inheritdoc />
public abstract Memory<T> this[int index] { get; }
@ -150,7 +150,7 @@ internal abstract partial class MemoryGroup<T> : IMemoryGroup<T>, IDisposable
long totalLengthInElements,
int bufferAlignmentInElements,
AllocationOptions options,
out MemoryGroup<T> memoryGroup)
[NotNullWhen(true)] out MemoryGroup<T>? memoryGroup)
{
Guard.NotNull(pool, nameof(pool));
Guard.MustBeGreaterThanOrEqualTo(totalLengthInElements, 0, nameof(totalLengthInElements));
@ -188,7 +188,7 @@ internal abstract partial class MemoryGroup<T> : IMemoryGroup<T>, IDisposable
bufferCount++;
}
UnmanagedMemoryHandle[] arrays = pool.Rent(bufferCount);
UnmanagedMemoryHandle[]? arrays = pool.Rent(bufferCount);
if (arrays == null)
{

Loading…
Cancel
Save