diff options
Diffstat (limited to 'ARMeilleure/IntermediateRepresentation/IntrusiveList.cs')
-rw-r--r-- | ARMeilleure/IntermediateRepresentation/IntrusiveList.cs | 86 |
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); + } } } |