SoftReferenceOptions
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace DotNext.Runtime
{
[NullableContext(1)]
[Nullable(0)]
public class SoftReferenceOptions
{
private readonly int collectionCount;
private readonly long memoryLimit = 9223372036854775807;
private readonly double memoryThreshold = 1;
public static SoftReferenceOptions Default { get; } = new SoftReferenceOptions();
public int CollectionCount {
get {
return collectionCount;
}
set {
if (value <= 0)
throw new ArgumentOutOfRangeException("value");
collectionCount = value;
}
}
public long MemoryLimit {
get {
return memoryLimit;
}
set {
if (value <= 0)
throw new ArgumentOutOfRangeException("value");
memoryLimit = value;
}
}
public double MemoryThreshold {
get {
return memoryThreshold;
}
set {
if (!double.IsFinite(value) || !(value > 0) || !(value <= 1))
throw new ArgumentOutOfRangeException("value");
memoryThreshold = value;
}
}
internal bool KeepTracking(object target)
{
int generation = GC.GetGeneration(target);
if (generation >= GC.MaxGeneration) {
if (GC.CollectionCount(generation) <= collectionCount)
return CheckLimits(generation);
return false;
}
return true;
}
private bool CheckLimits(int generation)
{
GCMemoryInfo info = GC.GetGCMemoryInfo();
if (info.Index != 0) {
if (CheckMemoryLimit(generation, ref info))
return CheckMemoryThreshold(ref info);
return false;
}
return true;
}
private bool CheckMemoryThreshold([In] [IsReadOnly] ref GCMemoryInfo info)
{
return (double)info.MemoryLoadBytes <= (double)info.HighMemoryLoadThresholdBytes * memoryThreshold;
}
private bool CheckMemoryLimit(int generation, [In] [IsReadOnly] ref GCMemoryInfo info)
{
if (memoryLimit != 9223372036854775807) {
ReadOnlySpan<GCGenerationInfo> generationInfo;
ReadOnlySpan<GCGenerationInfo> readOnlySpan = generationInfo = info.GenerationInfo;
if (readOnlySpan.Length > generation)
return generationInfo[generation].SizeAfterBytes < memoryLimit;
}
return true;
}
}
}