Created
May 7, 2024 13:15
-
-
Save kolebynov/79f70afaccde0307a8bf3219c2b1cc54 to your computer and use it in GitHub Desktop.
Simple stack/heap dynamic array
This file contains hidden or 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