aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/IntermediateRepresentation/IntrusiveList.cs
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/IntermediateRepresentation/IntrusiveList.cs')
-rw-r--r--ARMeilleure/IntermediateRepresentation/IntrusiveList.cs86
1 files changed, 58 insertions, 28 deletions
diff --git a/ARMeilleure/IntermediateRepresentation/IntrusiveList.cs b/ARMeilleure/IntermediateRepresentation/IntrusiveList.cs
index a7b0f7a7..184df87c 100644
--- a/ARMeilleure/IntermediateRepresentation/IntrusiveList.cs
+++ b/ARMeilleure/IntermediateRepresentation/IntrusiveList.cs
@@ -1,4 +1,6 @@
-using System.Diagnostics;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace ARMeilleure.IntermediateRepresentation
@@ -7,7 +9,7 @@ namespace ARMeilleure.IntermediateRepresentation
/// Represents a efficient linked list that stores the pointer on the object directly and does not allocate.
/// </summary>
/// <typeparam name="T">Type of the list items</typeparam>
- class IntrusiveList<T> where T : class, IIntrusiveListNode<T>
+ class IntrusiveList<T> where T : IEquatable<T>, IIntrusiveListNode<T>
{
/// <summary>
/// First item of the list, or null if empty.
@@ -25,21 +27,33 @@ namespace ARMeilleure.IntermediateRepresentation
public int Count { get; private set; }
/// <summary>
+ /// Initializes a new instance of the <see cref="IntrusiveList{T}"/> class.
+ /// </summary>
+ /// <exception cref="ArgumentException"><typeparamref name="T"/> is not pointer sized.</exception>
+ public IntrusiveList()
+ {
+ if (Unsafe.SizeOf<T>() != IntPtr.Size)
+ {
+ throw new ArgumentException("T must be a reference type or a pointer sized struct.");
+ }
+ }
+
+ /// <summary>
/// Adds a item as the first item of the list.
/// </summary>
/// <param name="newNode">Item to be added</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void AddFirst(T newNode)
+ public T AddFirst(T newNode)
{
- if (First != null)
+ if (!EqualsNull(First))
{
- AddBefore(First, newNode);
+ return AddBefore(First, newNode);
}
else
{
- Debug.Assert(newNode.ListPrevious == null);
- Debug.Assert(newNode.ListNext == null);
- Debug.Assert(Last == null);
+ Debug.Assert(EqualsNull(newNode.ListPrevious));
+ Debug.Assert(EqualsNull(newNode.ListNext));
+ Debug.Assert(EqualsNull(Last));
First = newNode;
Last = newNode;
@@ -47,6 +61,8 @@ namespace ARMeilleure.IntermediateRepresentation
Debug.Assert(Count == 0);
Count = 1;
+
+ return newNode;
}
}
@@ -55,17 +71,17 @@ namespace ARMeilleure.IntermediateRepresentation
/// </summary>
/// <param name="newNode">Item to be added</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void AddLast(T newNode)
+ public T AddLast(T newNode)
{
- if (Last != null)
+ if (!EqualsNull(Last))
{
- AddAfter(Last, newNode);
+ return AddAfter(Last, newNode);
}
else
{
- Debug.Assert(newNode.ListPrevious == null);
- Debug.Assert(newNode.ListNext == null);
- Debug.Assert(First == null);
+ Debug.Assert(EqualsNull(newNode.ListPrevious));
+ Debug.Assert(EqualsNull(newNode.ListNext));
+ Debug.Assert(EqualsNull(First));
First = newNode;
Last = newNode;
@@ -73,6 +89,8 @@ namespace ARMeilleure.IntermediateRepresentation
Debug.Assert(Count == 0);
Count = 1;
+
+ return newNode;
}
}
@@ -85,20 +103,20 @@ namespace ARMeilleure.IntermediateRepresentation
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T AddBefore(T node, T newNode)
{
- Debug.Assert(newNode.ListPrevious == null);
- Debug.Assert(newNode.ListNext == null);
+ Debug.Assert(EqualsNull(newNode.ListPrevious));
+ Debug.Assert(EqualsNull(newNode.ListNext));
newNode.ListPrevious = node.ListPrevious;
newNode.ListNext = node;
node.ListPrevious = newNode;
- if (newNode.ListPrevious != null)
+ if (!EqualsNull(newNode.ListPrevious))
{
newNode.ListPrevious.ListNext = newNode;
}
- if (First == node)
+ if (Equals(First, node))
{
First = newNode;
}
@@ -117,20 +135,20 @@ namespace ARMeilleure.IntermediateRepresentation
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T AddAfter(T node, T newNode)
{
- Debug.Assert(newNode.ListPrevious == null);
- Debug.Assert(newNode.ListNext == null);
+ Debug.Assert(EqualsNull(newNode.ListPrevious));
+ Debug.Assert(EqualsNull(newNode.ListNext));
newNode.ListPrevious = node;
newNode.ListNext = node.ListNext;
node.ListNext = newNode;
- if (newNode.ListNext != null)
+ if (!EqualsNull(newNode.ListNext))
{
newNode.ListNext.ListPrevious = newNode;
}
- if (Last == node)
+ if (Equals(Last, node))
{
Last = newNode;
}
@@ -147,32 +165,44 @@ namespace ARMeilleure.IntermediateRepresentation
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Remove(T node)
{
- if (node.ListPrevious != null)
+ if (!EqualsNull(node.ListPrevious))
{
node.ListPrevious.ListNext = node.ListNext;
}
else
{
- Debug.Assert(First == node);
+ Debug.Assert(Equals(First, node));
First = node.ListNext;
}
- if (node.ListNext != null)
+ if (!EqualsNull(node.ListNext))
{
node.ListNext.ListPrevious = node.ListPrevious;
}
else
{
- Debug.Assert(Last == node);
+ Debug.Assert(Equals(Last, node));
Last = node.ListPrevious;
}
- node.ListPrevious = null;
- node.ListNext = null;
+ node.ListPrevious = default;
+ node.ListNext = default;
Count--;
}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool EqualsNull(T a)
+ {
+ return EqualityComparer<T>.Default.Equals(a, default);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool Equals(T a, T b)
+ {
+ return EqualityComparer<T>.Default.Equals(a, b);
+ }
}
}