From 82582497a74a821a4fabf1d114fee660aa3756d7 Mon Sep 17 00:00:00 2001 From: FICTURE7 Date: Fri, 9 Apr 2021 19:47:09 +0400 Subject: [PATCH] Add EntryTable --- ARMeilleure/Common/EntryTable.cs | 100 +++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 ARMeilleure/Common/EntryTable.cs diff --git a/ARMeilleure/Common/EntryTable.cs b/ARMeilleure/Common/EntryTable.cs new file mode 100644 index 000000000..eef8445a5 --- /dev/null +++ b/ARMeilleure/Common/EntryTable.cs @@ -0,0 +1,100 @@ +using System; + +namespace ARMeilleure.Common +{ + /// + /// Represents a fixed size table of the type , whose entries will remain at the same + /// address through out the table's lifetime. + /// + /// Type of the entry in the table + class EntryTable where TEntry : unmanaged + { + private int _freeHint; + private readonly TEntry[] _table; + private readonly BitMap _allocated; + + /// + /// Initializes a new instance of the class with the specified capacity. + /// + /// Capacity of the table + /// is less than 0 + public EntryTable(int capacity) + { + if (capacity < 0) + { + throw new ArgumentOutOfRangeException(nameof(capacity)); + } + + _freeHint = 0; + _allocated = new BitMap(); + _table = GC.AllocateArray(capacity, pinned: true); + } + + /// + /// Tries to allocate an entry in the . Returns if + /// success; otherwise returns . + /// + /// Index of entry allocated in the table + /// if success; otherwise + public bool TryAllocate(out int index) + { + lock (_allocated) + { + if (_allocated.IsSet(_freeHint)) + { + _freeHint = _allocated.FindFirstUnset(); + } + + if (_freeHint < _table.Length) + { + index = checked(_freeHint++); + + _allocated.Set(index); + + return true; + } + } + + index = 0; + + return false; + } + + /// + /// Frees the entry at the specified . + /// + /// Index of entry to free + public void Free(int index) + { + lock (_allocated) + { + _allocated.Clear(index); + } + } + + /// + /// Gets a reference to the entry at the specified allocated . + /// + /// Index of the entry + /// Reference to the entry at the specified index + /// Entry at is not allocated + /// is outside of the table + public ref TEntry GetValue(int index) + { + if (index < 0 || index >= _table.Length) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + lock (_allocated) + { + if (!_allocated.IsSet(index)) + { + throw new ArgumentException("Entry at the specified index was not allocated", nameof(index)); + } + } + + return ref _table[index]; + } + } +}