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];
+ }
+ }
+}