Remove unsafe code from GrowableStack

This commit is contained in:
Pieter-Jan Briers
2021-02-12 13:10:17 +01:00
parent e0c63e7ce6
commit 5187040a64
2 changed files with 8 additions and 41 deletions

View File

@@ -870,7 +870,7 @@ namespace Robust.Shared.Physics
public void Query<TState>(ref TState state, QueryCallback<TState> callback, in Box2 aabb)
{
using var stack = new GrowableStack<Proxy>(stackalloc Proxy[256]);
var stack = new GrowableStack<Proxy>(stackalloc Proxy[256]);
stack.Push(_root);
ref var baseRef = ref _nodes[0];
@@ -915,7 +915,7 @@ namespace Robust.Shared.Physics
{
// NOTE: This is not Box2D's normal ray cast function, since our rays have infinite length.
using var stack = new GrowableStack<Proxy>(stackalloc Proxy[256]);
var stack = new GrowableStack<Proxy>(stackalloc Proxy[256]);
stack.Push(_root);

View File

@@ -1,5 +1,4 @@
using System;
using System.Runtime.InteropServices;
namespace Robust.Shared.Utility
{
@@ -10,62 +9,31 @@ namespace Robust.Shared.Utility
/// If the stack size exceeds the initial capacity, the heap is used
/// to increase the size of the stack.
/// </summary>
/// <remarks>
/// You MUST call <see cref="Dispose"/> when you are done with this stack or else you will have a memory leak.
/// </remarks>
/// <typeparam name="T">The type of elements in the stack.</typeparam>
internal unsafe ref struct GrowableStack<T> where T : unmanaged
internal ref struct GrowableStack<T> where T : unmanaged
{
// TODO: Switch to managed arrays for the on-heap alloc when we have .NET 5.
// Because with .NET 5 we can use the Pinned Object Heap.
private T* _stack;
private bool _wasReallocated;
private Span<T> _stack;
private int _count;
private int _capacity;
/// <summary>
/// Creates the growable stack with the allocated space as stack space.
/// </summary>
/// <remarks>
/// <paramref name="stackSpace"/> MUST BE A PIECE OF PINNED MEMORY,
/// OR ELSE YOU HAVE A MASSIVE GC BUG ON YOUR HAND.
/// </remarks>
public GrowableStack(Span<T> stackSpace)
{
fixed (T* ap = stackSpace)
{
_stack = ap;
}
_stack = stackSpace;
_capacity = stackSpace.Length;
_wasReallocated = false;
_count = 0;
}
public void Dispose()
{
if (_wasReallocated)
{
Marshal.FreeHGlobal((IntPtr) _stack);
_stack = null;
}
}
public void Push(in T element)
{
if (_count == _capacity)
{
var old = _stack;
_capacity *= 2;
var dstSize = _capacity * sizeof(T);
_stack = (T*) Marshal.AllocHGlobal(dstSize);
Buffer.MemoryCopy(old, _stack, dstSize, _count * sizeof(T));
if (_wasReallocated)
{
Marshal.FreeHGlobal((IntPtr) old);
}
_wasReallocated = true;
var oldStack = _stack;
_stack = GC.AllocateUninitializedArray<T>(_capacity);
oldStack.CopyTo(_stack);
}
_stack[_count] = element;
@@ -74,7 +42,6 @@ namespace Robust.Shared.Utility
public T Pop()
{
DebugTools.Assert(_count > 0);
--_count;
return _stack[_count];
}