-
-
Save dadhi/068e964d6b1747d82ecf9e2314f0cf6d to your computer and use it in GitHub Desktop.
Simple stack/heap dynamic array
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System.Runtime.InteropServices; | |
var list1 = new FixedList16<int>(); | |
var list2 = new FixedList32<int>(); | |
UseList(ref list1, 1); | |
UseList(ref list2, 2); | |
static void UseList<TItem, TList>(ref TList list, TItem item) | |
where TItem : unmanaged | |
where TList : IFixedList<TItem> | |
{ | |
list.Add(item); | |
} | |
public interface IFixedList<T> | |
where T : unmanaged | |
{ | |
int Count { get; } | |
ref T GetRef(int index); | |
void Add(T item); | |
} | |
public struct FixedListImpl<TElement, TBuffer> | |
where TElement : unmanaged | |
where TBuffer : unmanaged | |
{ | |
private static readonly int BufferSize = Unsafe.SizeOf<TBuffer>(); | |
private TBuffer _buffer; | |
private TElement[] _heapBuffer; | |
private int _count; | |
public int Count => _count; | |
public ref TElement GetRef(int index) | |
{ | |
// CheckIndex | |
return ref _heapBuffer != null | |
? ref _heapBuffer[index] | |
: ref MemoryMarshal.Cast<TBuffer, TElement>(MemoryMarshal.CreateSpan(ref _buffer, 1))[index]; | |
} | |
public void Add(TElement item) | |
{ | |
var span = MemoryMarshal.Cast<TBuffer, TElement>(MemoryMarshal.CreateSpan(ref _buffer, 1)); | |
if (_heapBuffer == null && span.Length > _count) | |
{ | |
span[_count++] = item; | |
return; | |
} | |
_heapBuffer ??= new TElement[16]; | |
// Reallocate heap buffer if needed | |
_heapBuffer[_count++] = item; | |
} | |
} | |
public struct FixedList16<T> : IFixedList<T> | |
where T : unmanaged | |
{ | |
private FixedListImpl<T, Buffer16> _impl; | |
public int Count => _impl.Count; | |
public ref T GetRef(int index) => ref _impl.GetRef(index); | |
public void Add(T item) => _impl.Add(item); | |
} | |
public struct FixedList32<T> : IFixedList<T> | |
where T : unmanaged | |
{ | |
private FixedListImpl<T, Buffer32> _impl; | |
public int Count => _impl.Count; | |
public ref T GetRef(int index) => ref _impl.GetRef(index); | |
public void Add(T item) => _impl.Add(item); | |
} | |
[InlineArray(16)] | |
public struct Buffer16 | |
{ | |
private byte _element0; | |
} | |
[InlineArray(32)] | |
public struct Buffer32 | |
{ | |
private byte _element0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment