// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; using osu.Framework.Statistics; namespace osu.Framework.Platform { /// /// Track native memory allocations via . /// Also adds memory pressure automatically. /// public static class NativeMemoryTracker { /// /// Add new tracked native memory. /// /// The object responsible for this allocation. /// The number of bytes allocated. /// A lease which should be disposed when memory is released. public static NativeMemoryLease AddMemory(object source, long amount) { getStatistic(source).Value += amount; GC.AddMemoryPressure(amount); return new NativeMemoryLease((source, amount), sender => removeMemory(sender.source, sender.amount)); } /// /// Remove previously tracked native memory. /// /// The object responsible for this allocation. /// The number of bytes allocated. private static void removeMemory(object source, long amount) { getStatistic(source).Value -= amount; GC.RemoveMemoryPressure(amount); } private static GlobalStatistic getStatistic(object source) => GlobalStatistics.Get("Native", source.GetType().Name); /// /// A leased on a native memory allocation. Should be disposed when the associated memory is freed. /// public class NativeMemoryLease : InvokeOnDisposal<(object source, long amount)> { internal NativeMemoryLease((object source, long amount) sender, Action<(object source, long amount)> action) : base(sender, action) { } private bool isDisposed; public override void Dispose() { if (isDisposed) throw new ObjectDisposedException(ToString(), $"{nameof(NativeMemoryLease)} should not be disposed more than once"); base.Dispose(); isDisposed = true; } } } }