using System; namespace ARMeilleure.Common { /// /// Represents a numeric counter which can be used for instrumentation of compiled code. /// /// Type of the counter class Counter : IDisposable where T : unmanaged { private bool _disposed; private readonly int _index; private readonly EntryTable _countTable; /// /// Initializes a new instance of the class from the specified /// instance and index. /// /// instance /// Index in the private Counter(EntryTable countTable, int index) { _countTable = countTable; _index = index; } /// /// Gets a reference to the value of the counter. /// /// instance was disposed public ref T Value { get { if (_disposed) { throw new ObjectDisposedException(null); } return ref _countTable.GetValue(_index); } } /// /// Releases all resources used by the instance. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Releases all unmanaged and optionally managed resources used by the instance. /// /// to dispose managed resources also; otherwise just unmanaged resouces protected virtual void Dispose(bool disposing) { if (!_disposed) { // The index into the EntryTable is essentially an unmanaged resource since we allocate and free the // resource ourselves. _countTable.Free(_index); _disposed = true; } } /// /// Frees resources used by instance. /// ~Counter() { Dispose(false); } /// /// Tries to create a instance from the specified instance. /// /// from which to create the /// instance if success; otherwise /// if success; otherwise /// is /// is unsupported public static bool TryCreate(EntryTable countTable, out Counter counter) { if (countTable == null) { throw new ArgumentNullException(nameof(countTable)); } if (typeof(T) != typeof(byte) && typeof(T) != typeof(sbyte) && typeof(T) != typeof(short) && typeof(T) != typeof(ushort) && typeof(T) != typeof(int) && typeof(T) != typeof(uint) && typeof(T) != typeof(long) && typeof(T) != typeof(ulong) && typeof(T) != typeof(nint) && typeof(T) != typeof(nuint) && typeof(T) != typeof(float) && typeof(T) != typeof(double)) { throw new ArgumentException("Counter does not support the specified type", nameof(countTable)); } if (countTable.TryAllocate(out int index)) { counter = new Counter(countTable, index); return true; } counter = null; return false; } } }