Browse Source

implemented TotalUndisposedAllocationCount

pull/1969/head
Anton Firszov 4 years ago
parent
commit
b16fd4c685
  1. 19
      src/ImageSharp/Diagnostics/MemoryDiagnostics.cs
  2. 13
      src/ImageSharp/Diagnostics/MemoryInfo.cs
  3. 46
      src/ImageSharp/Memory/Allocators/Internals/RefCountedMemoryLifetimeGuard.cs
  4. 2
      src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs
  5. 4
      src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.LifetimeGuards.cs
  6. 2
      src/ImageSharp/Memory/Allocators/Internals/UnmanagedBufferLifetimeGuard.cs
  7. 2
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs
  8. 1
      tests/ImageSharp.Tests/Memory/Allocators/MemoryDiagnosticsTests.cs
  9. 2
      tests/ImageSharp.Tests/Memory/Allocators/RefCountedLifetimeGuardTests.cs

19
src/ImageSharp/Diagnostics/MemoryDiagnostics.cs

@ -2,21 +2,22 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Threading;
namespace SixLabors.ImageSharp.Diagnostics
{
public readonly struct MemoryInfo
{
internal MemoryInfo(long totalUndisposedAllocationCount)
=> this.TotalUndisposedAllocationCount = totalUndisposedAllocationCount;
public long TotalUndisposedAllocationCount { get; }
}
public static class MemoryDiagnostics
{
public static MemoryInfo GetMemoryInfo() => throw new NotImplementedException();
private static int totalUndisposedAllocationCount;
public static MemoryInfo GetMemoryInfo() => new MemoryInfo(totalUndisposedAllocationCount);
public static bool EnableStrictDisposeWatcher { get; set; }
internal static void IncrementTotalUndisposedAllocationCount() =>
Interlocked.Increment(ref totalUndisposedAllocationCount);
internal static void DecrementTotalUndisposedAllocationCount() =>
Interlocked.Decrement(ref totalUndisposedAllocationCount);
}
}

13
src/ImageSharp/Diagnostics/MemoryInfo.cs

@ -0,0 +1,13 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Diagnostics
{
public readonly struct MemoryInfo
{
internal MemoryInfo(long totalUndisposedAllocationCount)
=> this.TotalUndisposedAllocationCount = totalUndisposedAllocationCount;
public long TotalUndisposedAllocationCount { get; }
}
}

46
src/ImageSharp/Memory/Allocators/Internals/RefCountedLifetimeGuard.cs → src/ImageSharp/Memory/Allocators/Internals/RefCountedMemoryLifetimeGuard.cs

@ -4,42 +4,33 @@
using System;
using System.Runtime.InteropServices;
using System.Threading;
using SixLabors.ImageSharp.Diagnostics;
namespace SixLabors.ImageSharp.Memory.Internals
{
/// <summary>
/// Implements reference counting lifetime guard mechanism similar to the one provided by <see cref="SafeHandle"/>,
/// but without the restriction of the guarded object being a handle.
/// Implements reference counting lifetime guard mechanism for memory resources
/// also maintaining the current value of <see cref="MemoryInfo.TotalUndisposedAllocationCount"/>.
/// </summary>
internal abstract class RefCountedLifetimeGuard : IDisposable
internal abstract class RefCountedMemoryLifetimeGuard : IDisposable
{
private int refCount = 1;
private int disposed;
private int released;
~RefCountedLifetimeGuard()
public RefCountedMemoryLifetimeGuard() => MemoryDiagnostics.IncrementTotalUndisposedAllocationCount();
~RefCountedMemoryLifetimeGuard()
{
Interlocked.Exchange(ref this.disposed, 1);
this.ReleaseRef();
this.ReleaseRef(true);
}
public bool IsDisposed => this.disposed == 1;
public void AddRef() => Interlocked.Increment(ref this.refCount);
public void ReleaseRef()
{
Interlocked.Decrement(ref this.refCount);
if (this.refCount == 0)
{
int wasReleased = Interlocked.Exchange(ref this.released, 1);
if (wasReleased == 0)
{
this.Release();
}
}
}
public void ReleaseRef() => this.ReleaseRef(false);
public void Dispose()
{
@ -52,5 +43,24 @@ namespace SixLabors.ImageSharp.Memory.Internals
}
protected abstract void Release();
private void ReleaseRef(bool finalizing)
{
Interlocked.Decrement(ref this.refCount);
if (this.refCount == 0)
{
int wasReleased = Interlocked.Exchange(ref this.released, 1);
if (wasReleased == 0)
{
if (!finalizing)
{
MemoryDiagnostics.DecrementTotalUndisposedAllocationCount();
}
this.Release();
}
}
}
}
}

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

@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.Memory.Internals
}
}
private sealed class LifetimeGuard : RefCountedLifetimeGuard
private sealed class LifetimeGuard : RefCountedMemoryLifetimeGuard
{
private byte[] array;

4
src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.LifetimeGuards.cs

@ -20,9 +20,9 @@ namespace SixLabors.ImageSharp.Memory.Internals
return buffer;
}
public RefCountedLifetimeGuard CreateGroupLifetimeGuard(UnmanagedMemoryHandle[] handles) => new GroupLifetimeGuard(this, handles);
public RefCountedMemoryLifetimeGuard CreateGroupLifetimeGuard(UnmanagedMemoryHandle[] handles) => new GroupLifetimeGuard(this, handles);
private sealed class GroupLifetimeGuard : RefCountedLifetimeGuard
private sealed class GroupLifetimeGuard : RefCountedMemoryLifetimeGuard
{
private readonly UniformUnmanagedMemoryPool pool;
private readonly UnmanagedMemoryHandle[] handles;

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

@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Memory.Internals
/// <summary>
/// Defines a strategy for managing unmanaged memory ownership.
/// </summary>
internal abstract class UnmanagedBufferLifetimeGuard : RefCountedLifetimeGuard
internal abstract class UnmanagedBufferLifetimeGuard : RefCountedMemoryLifetimeGuard
{
private UnmanagedMemoryHandle handle;

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

@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Memory
public sealed class Owned : MemoryGroup<T>, IEnumerable<Memory<T>>
{
private IMemoryOwner<T>[] memoryOwners;
private RefCountedLifetimeGuard groupLifetimeGuard;
private RefCountedMemoryLifetimeGuard groupLifetimeGuard;
public Owned(IMemoryOwner<T>[] memoryOwners, int bufferLength, long totalLength, bool swappable)
: base(bufferLength, totalLength)

1
tests/ImageSharp.Tests/Memory/Allocators/MemoryDiagnosticsTests.cs

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Microsoft.DotNet.RemoteExecutor;

2
tests/ImageSharp.Tests/Memory/Allocators/RefCountedLifetimeGuardTests.cs

@ -110,7 +110,7 @@ namespace SixLabors.ImageSharp.Tests.Memory.Allocators
}
}
private class MockLifetimeGuard : RefCountedLifetimeGuard
private class MockLifetimeGuard : RefCountedMemoryLifetimeGuard
{
public int ReleaseInvocationCount { get; private set; }

Loading…
Cancel
Save