aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Common
diff options
context:
space:
mode:
authorTSR Berry <20988865+TSRBerry@users.noreply.github.com>2023-04-08 01:22:00 +0200
committerMary <thog@protonmail.com>2023-04-27 23:51:14 +0200
commitcee712105850ac3385cd0091a923438167433f9f (patch)
tree4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /ARMeilleure/Common
parentcd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff)
Move solution and projects to src
Diffstat (limited to 'ARMeilleure/Common')
-rw-r--r--ARMeilleure/Common/AddressTable.cs252
-rw-r--r--ARMeilleure/Common/Allocator.cs24
-rw-r--r--ARMeilleure/Common/ArenaAllocator.cs187
-rw-r--r--ARMeilleure/Common/BitMap.cs222
-rw-r--r--ARMeilleure/Common/BitUtils.cs57
-rw-r--r--ARMeilleure/Common/Counter.cs98
-rw-r--r--ARMeilleure/Common/EntryTable.cs188
-rw-r--r--ARMeilleure/Common/EnumUtils.cs12
-rw-r--r--ARMeilleure/Common/NativeAllocator.cs27
9 files changed, 0 insertions, 1067 deletions
diff --git a/ARMeilleure/Common/AddressTable.cs b/ARMeilleure/Common/AddressTable.cs
deleted file mode 100644
index 9db2d00d..00000000
--- a/ARMeilleure/Common/AddressTable.cs
+++ /dev/null
@@ -1,252 +0,0 @@
-using ARMeilleure.Diagnostics;
-using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-
-namespace ARMeilleure.Common
-{
- /// <summary>
- /// Represents a table of guest address to a value.
- /// </summary>
- /// <typeparam name="TEntry">Type of the value</typeparam>
- unsafe class AddressTable<TEntry> : IDisposable where TEntry : unmanaged
- {
- /// <summary>
- /// Represents a level in an <see cref="AddressTable{TEntry}"/>.
- /// </summary>
- public readonly struct Level
- {
- /// <summary>
- /// Gets the index of the <see cref="Level"/> in the guest address.
- /// </summary>
- public int Index { get; }
-
- /// <summary>
- /// Gets the length of the <see cref="Level"/> in the guest address.
- /// </summary>
- public int Length { get; }
-
- /// <summary>
- /// Gets the mask which masks the bits used by the <see cref="Level"/>.
- /// </summary>
- public ulong Mask => ((1ul << Length) - 1) << Index;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="Level"/> structure with the specified
- /// <paramref name="index"/> and <paramref name="length"/>.
- /// </summary>
- /// <param name="index">Index of the <see cref="Level"/></param>
- /// <param name="length">Length of the <see cref="Level"/></param>
- public Level(int index, int length)
- {
- (Index, Length) = (index, length);
- }
-
- /// <summary>
- /// Gets the value of the <see cref="Level"/> from the specified guest <paramref name="address"/>.
- /// </summary>
- /// <param name="address">Guest address</param>
- /// <returns>Value of the <see cref="Level"/> from the specified guest <paramref name="address"/></returns>
- public int GetValue(ulong address)
- {
- return (int)((address & Mask) >> Index);
- }
- }
-
- private bool _disposed;
- private TEntry** _table;
- private readonly List<IntPtr> _pages;
-
- /// <summary>
- /// Gets the bits used by the <see cref="Levels"/> of the <see cref="AddressTable{TEntry}"/> instance.
- /// </summary>
- public ulong Mask { get; }
-
- /// <summary>
- /// Gets the <see cref="Level"/>s used by the <see cref="AddressTable{TEntry}"/> instance.
- /// </summary>
- public Level[] Levels { get; }
-
- /// <summary>
- /// Gets or sets the default fill value of newly created leaf pages.
- /// </summary>
- public TEntry Fill { get; set; }
-
- /// <summary>
- /// Gets the base address of the <see cref="EntryTable{TEntry}"/>.
- /// </summary>
- /// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
- public IntPtr Base
- {
- get
- {
- ObjectDisposedException.ThrowIf(_disposed, this);
-
- lock (_pages)
- {
- return (IntPtr)GetRootPage();
- }
- }
- }
-
- /// <summary>
- /// Constructs a new instance of the <see cref="AddressTable{TEntry}"/> class with the specified list of
- /// <see cref="Level"/>.
- /// </summary>
- /// <exception cref="ArgumentNullException"><paramref name="levels"/> is null</exception>
- /// <exception cref="ArgumentException">Length of <paramref name="levels"/> is less than 2</exception>
- public AddressTable(Level[] levels)
- {
- ArgumentNullException.ThrowIfNull(levels);
-
- if (levels.Length < 2)
- {
- throw new ArgumentException("Table must be at least 2 levels deep.", nameof(levels));
- }
-
- _pages = new List<IntPtr>(capacity: 16);
-
- Levels = levels;
- Mask = 0;
-
- foreach (var level in Levels)
- {
- Mask |= level.Mask;
- }
- }
-
- /// <summary>
- /// Determines if the specified <paramref name="address"/> is in the range of the
- /// <see cref="AddressTable{TEntry}"/>.
- /// </summary>
- /// <param name="address">Guest address</param>
- /// <returns><see langword="true"/> if is valid; otherwise <see langword="false"/></returns>
- public bool IsValid(ulong address)
- {
- return (address & ~Mask) == 0;
- }
-
- /// <summary>
- /// Gets a reference to the value at the specified guest <paramref name="address"/>.
- /// </summary>
- /// <param name="address">Guest address</param>
- /// <returns>Reference to the value at the specified guest <paramref name="address"/></returns>
- /// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
- /// <exception cref="ArgumentException"><paramref name="address"/> is not mapped</exception>
- public ref TEntry GetValue(ulong address)
- {
- ObjectDisposedException.ThrowIf(_disposed, this);
-
- if (!IsValid(address))
- {
- throw new ArgumentException($"Address 0x{address:X} is not mapped onto the table.", nameof(address));
- }
-
- lock (_pages)
- {
- return ref GetPage(address)[Levels[^1].GetValue(address)];
- }
- }
-
- /// <summary>
- /// Gets the leaf page for the specified guest <paramref name="address"/>.
- /// </summary>
- /// <param name="address">Guest address</param>
- /// <returns>Leaf page for the specified guest <paramref name="address"/></returns>
- private TEntry* GetPage(ulong address)
- {
- TEntry** page = GetRootPage();
-
- for (int i = 0; i < Levels.Length - 1; i++)
- {
- ref Level level = ref Levels[i];
- ref TEntry* nextPage = ref page[level.GetValue(address)];
-
- if (nextPage == null)
- {
- ref Level nextLevel = ref Levels[i + 1];
-
- nextPage = i == Levels.Length - 2 ?
- (TEntry*)Allocate(1 << nextLevel.Length, Fill, leaf: true) :
- (TEntry*)Allocate(1 << nextLevel.Length, IntPtr.Zero, leaf: false);
- }
-
- page = (TEntry**)nextPage;
- }
-
- return (TEntry*)page;
- }
-
- /// <summary>
- /// Lazily initialize and get the root page of the <see cref="AddressTable{TEntry}"/>.
- /// </summary>
- /// <returns>Root page of the <see cref="AddressTable{TEntry}"/></returns>
- private TEntry** GetRootPage()
- {
- if (_table == null)
- {
- _table = (TEntry**)Allocate(1 << Levels[0].Length, fill: IntPtr.Zero, leaf: false);
- }
-
- return _table;
- }
-
- /// <summary>
- /// Allocates a block of memory of the specified type and length.
- /// </summary>
- /// <typeparam name="T">Type of elements</typeparam>
- /// <param name="length">Number of elements</param>
- /// <param name="fill">Fill value</param>
- /// <param name="leaf"><see langword="true"/> if leaf; otherwise <see langword="false"/></param>
- /// <returns>Allocated block</returns>
- private IntPtr Allocate<T>(int length, T fill, bool leaf) where T : unmanaged
- {
- var size = sizeof(T) * length;
- var page = (IntPtr)NativeAllocator.Instance.Allocate((uint)size);
- var span = new Span<T>((void*)page, length);
-
- span.Fill(fill);
-
- _pages.Add(page);
-
- TranslatorEventSource.Log.AddressTableAllocated(size, leaf);
-
- return page;
- }
-
- /// <summary>
- /// Releases all resources used by the <see cref="AddressTable{TEntry}"/> instance.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- /// <summary>
- /// Releases all unmanaged and optionally managed resources used by the <see cref="AddressTable{TEntry}"/>
- /// instance.
- /// </summary>
- /// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resouces</param>
- protected virtual void Dispose(bool disposing)
- {
- if (!_disposed)
- {
- foreach (var page in _pages)
- {
- Marshal.FreeHGlobal(page);
- }
-
- _disposed = true;
- }
- }
-
- /// <summary>
- /// Frees resources used by the <see cref="AddressTable{TEntry}"/> instance.
- /// </summary>
- ~AddressTable()
- {
- Dispose(false);
- }
- }
-}
diff --git a/ARMeilleure/Common/Allocator.cs b/ARMeilleure/Common/Allocator.cs
deleted file mode 100644
index 247a8e8b..00000000
--- a/ARMeilleure/Common/Allocator.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System;
-
-namespace ARMeilleure.Common
-{
- unsafe abstract class Allocator : IDisposable
- {
- public T* Allocate<T>(ulong count = 1) where T : unmanaged
- {
- return (T*)Allocate(count * (uint)sizeof(T));
- }
-
- public abstract void* Allocate(ulong size);
-
- public abstract void Free(void* block);
-
- protected virtual void Dispose(bool disposing) { }
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- }
-}
diff --git a/ARMeilleure/Common/ArenaAllocator.cs b/ARMeilleure/Common/ArenaAllocator.cs
deleted file mode 100644
index bce6794a..00000000
--- a/ARMeilleure/Common/ArenaAllocator.cs
+++ /dev/null
@@ -1,187 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-
-namespace ARMeilleure.Common
-{
- unsafe sealed class ArenaAllocator : Allocator
- {
- private class PageInfo
- {
- public byte* Pointer;
- public byte Unused;
- public int UnusedCounter;
- }
-
- private int _lastReset;
- private ulong _index;
- private int _pageIndex;
- private PageInfo _page;
- private List<PageInfo> _pages;
- private readonly ulong _pageSize;
- private readonly uint _pageCount;
- private readonly List<IntPtr> _extras;
-
- public ArenaAllocator(uint pageSize, uint pageCount)
- {
- _lastReset = Environment.TickCount;
-
- // Set _index to pageSize so that the first allocation goes through the slow path.
- _index = pageSize;
- _pageIndex = -1;
-
- _page = null;
- _pages = new List<PageInfo>();
- _pageSize = pageSize;
- _pageCount = pageCount;
-
- _extras = new List<IntPtr>();
- }
-
- public Span<T> AllocateSpan<T>(ulong count) where T : unmanaged
- {
- return new Span<T>(Allocate<T>(count), (int)count);
- }
-
- public override void* Allocate(ulong size)
- {
- if (_index + size <= _pageSize)
- {
- byte* result = _page.Pointer + _index;
-
- _index += size;
-
- return result;
- }
-
- return AllocateSlow(size);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private void* AllocateSlow(ulong size)
- {
- if (size > _pageSize)
- {
- void* extra = NativeAllocator.Instance.Allocate(size);
-
- _extras.Add((IntPtr)extra);
-
- return extra;
- }
-
- if (_index + size > _pageSize)
- {
- _index = 0;
- _pageIndex++;
- }
-
- if (_pageIndex < _pages.Count)
- {
- _page = _pages[_pageIndex];
- _page.Unused = 0;
- }
- else
- {
- _page = new PageInfo();
- _page.Pointer = (byte*)NativeAllocator.Instance.Allocate(_pageSize);
-
- _pages.Add(_page);
- }
-
- byte* result = _page.Pointer + _index;
-
- _index += size;
-
- return result;
- }
-
- public override void Free(void* block) { }
-
- public void Reset()
- {
- _index = _pageSize;
- _pageIndex = -1;
- _page = null;
-
- // Free excess pages that was allocated.
- while (_pages.Count > _pageCount)
- {
- NativeAllocator.Instance.Free(_pages[_pages.Count - 1].Pointer);
-
- _pages.RemoveAt(_pages.Count - 1);
- }
-
- // Free extra blocks that are not page-sized
- foreach (IntPtr ptr in _extras)
- {
- NativeAllocator.Instance.Free((void*)ptr);
- }
-
- _extras.Clear();
-
- // Free pooled pages that has not been used in a while. Remove pages at the back first, because we try to
- // keep the pages at the front alive, since they're more likely to be hot and in the d-cache.
- bool removing = true;
-
- // If arena is used frequently, keep pages for longer. Otherwise keep pages for a shorter amount of time.
- int now = Environment.TickCount;
- int count = (now - _lastReset) switch {
- >= 5000 => 0,
- >= 2500 => 50,
- >= 1000 => 100,
- >= 10 => 1500,
- _ => 5000
- };
-
- for (int i = _pages.Count - 1; i >= 0; i--)
- {
- PageInfo page = _pages[i];
-
- if (page.Unused == 0)
- {
- page.UnusedCounter = 0;
- }
-
- page.UnusedCounter += page.Unused;
- page.Unused = 1;
-
- // If page not used after `count` resets, remove it.
- if (removing && page.UnusedCounter >= count)
- {
- NativeAllocator.Instance.Free(page.Pointer);
-
- _pages.RemoveAt(i);
- }
- else
- {
- removing = false;
- }
- }
-
- _lastReset = now;
- }
-
- protected override void Dispose(bool disposing)
- {
- if (_pages != null)
- {
- foreach (PageInfo info in _pages)
- {
- NativeAllocator.Instance.Free(info.Pointer);
- }
-
- foreach (IntPtr ptr in _extras)
- {
- NativeAllocator.Instance.Free((void*)ptr);
- }
-
- _pages = null;
- }
- }
-
- ~ArenaAllocator()
- {
- Dispose(false);
- }
- }
-}
diff --git a/ARMeilleure/Common/BitMap.cs b/ARMeilleure/Common/BitMap.cs
deleted file mode 100644
index 27ef031f..00000000
--- a/ARMeilleure/Common/BitMap.cs
+++ /dev/null
@@ -1,222 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Numerics;
-using System.Runtime.CompilerServices;
-
-namespace ARMeilleure.Common
-{
- unsafe class BitMap : IEnumerable<int>, IDisposable
- {
- private const int IntSize = 64;
- private const int IntMask = IntSize - 1;
-
- private int _count;
- private long* _masks;
- private readonly Allocator _allocator;
-
- public BitMap(Allocator allocator)
- {
- _allocator = allocator;
- }
-
- public BitMap(Allocator allocator, int capacity) : this(allocator)
- {
- EnsureCapacity(capacity);
- }
-
- public bool Set(int bit)
- {
- EnsureCapacity(bit + 1);
-
- int wordIndex = bit / IntSize;
- int wordBit = bit & IntMask;
-
- long wordMask = 1L << wordBit;
-
- if ((_masks[wordIndex] & wordMask) != 0)
- {
- return false;
- }
-
- _masks[wordIndex] |= wordMask;
-
- return true;
- }
-
- public void Clear(int bit)
- {
- EnsureCapacity(bit + 1);
-
- int wordIndex = bit / IntSize;
- int wordBit = bit & IntMask;
-
- long wordMask = 1L << wordBit;
-
- _masks[wordIndex] &= ~wordMask;
- }
-
- public bool IsSet(int bit)
- {
- EnsureCapacity(bit + 1);
-
- int wordIndex = bit / IntSize;
- int wordBit = bit & IntMask;
-
- return (_masks[wordIndex] & (1L << wordBit)) != 0;
- }
-
- public int FindFirstUnset()
- {
- for (int index = 0; index < _count; index++)
- {
- long mask = _masks[index];
-
- if (mask != -1L)
- {
- return BitOperations.TrailingZeroCount(~mask) + index * IntSize;
- }
- }
-
- return _count * IntSize;
- }
-
- public bool Set(BitMap map)
- {
- EnsureCapacity(map._count * IntSize);
-
- bool modified = false;
-
- for (int index = 0; index < _count; index++)
- {
- long newValue = _masks[index] | map._masks[index];
-
- if (_masks[index] != newValue)
- {
- _masks[index] = newValue;
-
- modified = true;
- }
- }
-
- return modified;
- }
-
- public bool Clear(BitMap map)
- {
- EnsureCapacity(map._count * IntSize);
-
- bool modified = false;
-
- for (int index = 0; index < _count; index++)
- {
- long newValue = _masks[index] & ~map._masks[index];
-
- if (_masks[index] != newValue)
- {
- _masks[index] = newValue;
-
- modified = true;
- }
- }
-
- return modified;
- }
-
- private void EnsureCapacity(int size)
- {
- int count = (size + IntMask) / IntSize;
-
- if (count > _count)
- {
- var oldMask = _masks;
- var oldSpan = new Span<long>(_masks, _count);
-
- _masks = _allocator.Allocate<long>((uint)count);
- _count = count;
-
- var newSpan = new Span<long>(_masks, _count);
-
- oldSpan.CopyTo(newSpan);
- newSpan.Slice(oldSpan.Length).Clear();
-
- _allocator.Free(oldMask);
- }
- }
-
- public void Dispose()
- {
- if (_masks != null)
- {
- _allocator.Free(_masks);
-
- _masks = null;
- }
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
-
- IEnumerator<int> IEnumerable<int>.GetEnumerator()
- {
- return GetEnumerator();
- }
-
- public Enumerator GetEnumerator()
- {
- return new Enumerator(this);
- }
-
- public struct Enumerator : IEnumerator<int>
- {
- private long _index;
- private long _mask;
- private int _bit;
- private readonly BitMap _map;
-
- public int Current => (int)_index * IntSize + _bit;
- object IEnumerator.Current => Current;
-
- public Enumerator(BitMap map)
- {
- _index = -1;
- _mask = 0;
- _bit = 0;
- _map = map;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool MoveNext()
- {
- if (_mask != 0)
- {
- _mask &= ~(1L << _bit);
- }
-
- // Manually hoist these loads, because RyuJIT does not.
- long count = (uint)_map._count;
- long* masks = _map._masks;
-
- while (_mask == 0)
- {
- if (++_index >= count)
- {
- return false;
- }
-
- _mask = masks[_index];
- }
-
- _bit = BitOperations.TrailingZeroCount(_mask);
-
- return true;
- }
-
- public void Reset() { }
-
- public void Dispose() { }
- }
- }
-} \ No newline at end of file
diff --git a/ARMeilleure/Common/BitUtils.cs b/ARMeilleure/Common/BitUtils.cs
deleted file mode 100644
index e7697ff3..00000000
--- a/ARMeilleure/Common/BitUtils.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-using System;
-using System.Numerics;
-
-namespace ARMeilleure.Common
-{
- static class BitUtils
- {
- private static ReadOnlySpan<sbyte> HbsNibbleLut => new sbyte[] { -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 };
-
- public static long FillWithOnes(int bits)
- {
- return bits == 64 ? -1L : (1L << bits) - 1;
- }
-
- public static int HighestBitSet(int value)
- {
- return 31 - BitOperations.LeadingZeroCount((uint)value);
- }
-
- public static int HighestBitSetNibble(int value)
- {
- return HbsNibbleLut[value];
- }
-
- public static long Replicate(long bits, int size)
- {
- long output = 0;
-
- for (int bit = 0; bit < 64; bit += size)
- {
- output |= bits << bit;
- }
-
- return output;
- }
-
- public static int RotateRight(int bits, int shift, int size)
- {
- return (int)RotateRight((uint)bits, shift, size);
- }
-
- public static uint RotateRight(uint bits, int shift, int size)
- {
- return (bits >> shift) | (bits << (size - shift));
- }
-
- public static long RotateRight(long bits, int shift, int size)
- {
- return (long)RotateRight((ulong)bits, shift, size);
- }
-
- public static ulong RotateRight(ulong bits, int shift, int size)
- {
- return (bits >> shift) | (bits << (size - shift));
- }
- }
-}
diff --git a/ARMeilleure/Common/Counter.cs b/ARMeilleure/Common/Counter.cs
deleted file mode 100644
index d7210d15..00000000
--- a/ARMeilleure/Common/Counter.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-using System;
-
-namespace ARMeilleure.Common
-{
- /// <summary>
- /// Represents a numeric counter which can be used for instrumentation of compiled code.
- /// </summary>
- /// <typeparam name="T">Type of the counter</typeparam>
- class Counter<T> : IDisposable where T : unmanaged
- {
- private bool _disposed;
- /// <summary>
- /// Index in the <see cref="EntryTable{T}"/>
- /// </summary>
- private readonly int _index;
- private readonly EntryTable<T> _countTable;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="Counter{T}"/> class from the specified
- /// <see cref="EntryTable{T}"/> instance and index.
- /// </summary>
- /// <param name="countTable"><see cref="EntryTable{T}"/> instance</param>
- /// <exception cref="ArgumentNullException"><paramref name="countTable"/> is <see langword="null"/></exception>
- /// <exception cref="ArgumentException"><typeparamref name="T"/> is unsupported</exception>
- public Counter(EntryTable<T> 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.");
- }
-
- _countTable = countTable ?? throw new ArgumentNullException(nameof(countTable));
- _index = countTable.Allocate();
- }
-
- /// <summary>
- /// Gets a reference to the value of the counter.
- /// </summary>
- /// <exception cref="ObjectDisposedException"><see cref="Counter{T}"/> instance was disposed</exception>
- /// <remarks>
- /// This can refer to freed memory if the owning <see cref="EntryTable{TEntry}"/> is disposed.
- /// </remarks>
- public ref T Value
- {
- get
- {
- ObjectDisposedException.ThrowIf(_disposed, this);
-
- return ref _countTable.GetValue(_index);
- }
- }
-
- /// <summary>
- /// Releases all resources used by the <see cref="Counter{T}"/> instance.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- /// <summary>
- /// Releases all unmanaged and optionally managed resources used by the <see cref="Counter{T}"/> instance.
- /// </summary>
- /// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resources</param>
- protected virtual void Dispose(bool disposing)
- {
- if (!_disposed)
- {
- try
- {
- // The index into the EntryTable is essentially an unmanaged resource since we allocate and free the
- // resource ourselves.
- _countTable.Free(_index);
- }
- catch (ObjectDisposedException)
- {
- // Can happen because _countTable may be disposed before the Counter instance.
- }
-
- _disposed = true;
- }
- }
-
- /// <summary>
- /// Frees resources used by the <see cref="Counter{T}"/> instance.
- /// </summary>
- ~Counter()
- {
- Dispose(false);
- }
- }
-}
diff --git a/ARMeilleure/Common/EntryTable.cs b/ARMeilleure/Common/EntryTable.cs
deleted file mode 100644
index 6f205797..00000000
--- a/ARMeilleure/Common/EntryTable.cs
+++ /dev/null
@@ -1,188 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Numerics;
-
-namespace ARMeilleure.Common
-{
- /// <summary>
- /// Represents an expandable table of the type <typeparamref name="TEntry"/>, whose entries will remain at the same
- /// address through out the table's lifetime.
- /// </summary>
- /// <typeparam name="TEntry">Type of the entry in the table</typeparam>
- class EntryTable<TEntry> : IDisposable where TEntry : unmanaged
- {
- private bool _disposed;
- private int _freeHint;
- private readonly int _pageCapacity; // Number of entries per page.
- private readonly int _pageLogCapacity;
- private readonly Dictionary<int, IntPtr> _pages;
- private readonly BitMap _allocated;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="EntryTable{TEntry}"/> class with the desired page size in
- /// bytes.
- /// </summary>
- /// <param name="pageSize">Desired page size in bytes</param>
- /// <exception cref="ArgumentOutOfRangeException"><paramref name="pageSize"/> is less than 0</exception>
- /// <exception cref="ArgumentException"><typeparamref name="TEntry"/>'s size is zero</exception>
- /// <remarks>
- /// The actual page size may be smaller or larger depending on the size of <typeparamref name="TEntry"/>.
- /// </remarks>
- public unsafe EntryTable(int pageSize = 4096)
- {
- if (pageSize < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(pageSize), "Page size cannot be negative.");
- }
-
- if (sizeof(TEntry) == 0)
- {
- throw new ArgumentException("Size of TEntry cannot be zero.");
- }
-
- _allocated = new BitMap(NativeAllocator.Instance);
- _pages = new Dictionary<int, IntPtr>();
- _pageLogCapacity = BitOperations.Log2((uint)(pageSize / sizeof(TEntry)));
- _pageCapacity = 1 << _pageLogCapacity;
- }
-
- /// <summary>
- /// Allocates an entry in the <see cref="EntryTable{TEntry}"/>.
- /// </summary>
- /// <returns>Index of entry allocated in the table</returns>
- /// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
- public int Allocate()
- {
- ObjectDisposedException.ThrowIf(_disposed, this);
-
- lock (_allocated)
- {
- if (_allocated.IsSet(_freeHint))
- {
- _freeHint = _allocated.FindFirstUnset();
- }
-
- int index = _freeHint++;
- var page = GetPage(index);
-
- _allocated.Set(index);
-
- GetValue(page, index) = default;
-
- return index;
- }
- }
-
- /// <summary>
- /// Frees the entry at the specified <paramref name="index"/>.
- /// </summary>
- /// <param name="index">Index of entry to free</param>
- /// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
- public void Free(int index)
- {
- ObjectDisposedException.ThrowIf(_disposed, this);
-
- lock (_allocated)
- {
- if (_allocated.IsSet(index))
- {
- _allocated.Clear(index);
-
- _freeHint = index;
- }
- }
- }
-
- /// <summary>
- /// Gets a reference to the entry at the specified allocated <paramref name="index"/>.
- /// </summary>
- /// <param name="index">Index of the entry</param>
- /// <returns>Reference to the entry at the specified <paramref name="index"/></returns>
- /// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
- /// <exception cref="ArgumentException">Entry at <paramref name="index"/> is not allocated</exception>
- public ref TEntry GetValue(int index)
- {
- ObjectDisposedException.ThrowIf(_disposed, this);
-
- lock (_allocated)
- {
- if (!_allocated.IsSet(index))
- {
- throw new ArgumentException("Entry at the specified index was not allocated", nameof(index));
- }
-
- var page = GetPage(index);
-
- return ref GetValue(page, index);
- }
- }
-
- /// <summary>
- /// Gets a reference to the entry at using the specified <paramref name="index"/> from the specified
- /// <paramref name="page"/>.
- /// </summary>
- /// <param name="page">Page to use</param>
- /// <param name="index">Index to use</param>
- /// <returns>Reference to the entry</returns>
- private ref TEntry GetValue(Span<TEntry> page, int index)
- {
- return ref page[index & (_pageCapacity - 1)];
- }
-
- /// <summary>
- /// Gets the page for the specified <see cref="index"/>.
- /// </summary>
- /// <param name="index">Index to use</param>
- /// <returns>Page for the specified <see cref="index"/></returns>
- private unsafe Span<TEntry> GetPage(int index)
- {
- var pageIndex = (int)((uint)(index & ~(_pageCapacity - 1)) >> _pageLogCapacity);
-
- if (!_pages.TryGetValue(pageIndex, out IntPtr page))
- {
- page = (IntPtr)NativeAllocator.Instance.Allocate((uint)sizeof(TEntry) * (uint)_pageCapacity);
-
- _pages.Add(pageIndex, page);
- }
-
- return new Span<TEntry>((void*)page, _pageCapacity);
- }
-
- /// <summary>
- /// Releases all resources used by the <see cref="EntryTable{TEntry}"/> instance.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- /// <summary>
- /// Releases all unmanaged and optionally managed resources used by the <see cref="EntryTable{TEntry}"/>
- /// instance.
- /// </summary>
- /// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resouces</param>
- protected unsafe virtual void Dispose(bool disposing)
- {
- if (!_disposed)
- {
- _allocated.Dispose();
-
- foreach (var page in _pages.Values)
- {
- NativeAllocator.Instance.Free((void*)page);
- }
-
- _disposed = true;
- }
- }
-
- /// <summary>
- /// Frees resources used by the <see cref="EntryTable{TEntry}"/> instance.
- /// </summary>
- ~EntryTable()
- {
- Dispose(false);
- }
- }
-}
diff --git a/ARMeilleure/Common/EnumUtils.cs b/ARMeilleure/Common/EnumUtils.cs
deleted file mode 100644
index 2a4aa645..00000000
--- a/ARMeilleure/Common/EnumUtils.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-
-namespace ARMeilleure.Common
-{
- static class EnumUtils
- {
- public static int GetCount(Type enumType)
- {
- return Enum.GetNames(enumType).Length;
- }
- }
-}
diff --git a/ARMeilleure/Common/NativeAllocator.cs b/ARMeilleure/Common/NativeAllocator.cs
deleted file mode 100644
index 71c04a9b..00000000
--- a/ARMeilleure/Common/NativeAllocator.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace ARMeilleure.Common
-{
- unsafe sealed class NativeAllocator : Allocator
- {
- public static NativeAllocator Instance { get; } = new();
-
- public override void* Allocate(ulong size)
- {
- void* result = (void*)Marshal.AllocHGlobal((IntPtr)size);
-
- if (result == null)
- {
- throw new OutOfMemoryException();
- }
-
- return result;
- }
-
- public override void Free(void* block)
- {
- Marshal.FreeHGlobal((IntPtr)block);
- }
- }
-}