| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Runtime.CompilerServices;
- namespace ARMeilleure.IntermediateRepresentation
- {
- /// <summary>
- /// 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 : IEquatable<T>, IIntrusiveListNode<T>
- {
- /// <summary>
- /// First item of the list, or null if empty.
- /// </summary>
- public T First { get; private set; }
- /// <summary>
- /// Last item of the list, or null if empty.
- /// </summary>
- public T Last { get; private set; }
- /// <summary>
- /// Total number of items on the list.
- /// </summary>
- 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 T AddFirst(T newNode)
- {
- if (!EqualsNull(First))
- {
- return AddBefore(First, newNode);
- }
- else
- {
- Debug.Assert(EqualsNull(newNode.ListPrevious));
- Debug.Assert(EqualsNull(newNode.ListNext));
- Debug.Assert(EqualsNull(Last));
- First = newNode;
- Last = newNode;
- Debug.Assert(Count == 0);
- Count = 1;
- return newNode;
- }
- }
- /// <summary>
- /// Adds a item as the last item of the list.
- /// </summary>
- /// <param name="newNode">Item to be added</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public T AddLast(T newNode)
- {
- if (!EqualsNull(Last))
- {
- return AddAfter(Last, newNode);
- }
- else
- {
- Debug.Assert(EqualsNull(newNode.ListPrevious));
- Debug.Assert(EqualsNull(newNode.ListNext));
- Debug.Assert(EqualsNull(First));
- First = newNode;
- Last = newNode;
- Debug.Assert(Count == 0);
- Count = 1;
- return newNode;
- }
- }
- /// <summary>
- /// Adds a item before a existing item on the list.
- /// </summary>
- /// <param name="node">Item on the list that will succeed the new item</param>
- /// <param name="newNode">Item to be added</param>
- /// <returns>New item</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public T AddBefore(T node, T newNode)
- {
- Debug.Assert(EqualsNull(newNode.ListPrevious));
- Debug.Assert(EqualsNull(newNode.ListNext));
- newNode.ListPrevious = node.ListPrevious;
- newNode.ListNext = node;
- node.ListPrevious = newNode;
- if (!EqualsNull(newNode.ListPrevious))
- {
- newNode.ListPrevious.ListNext = newNode;
- }
- if (Equals(First, node))
- {
- First = newNode;
- }
- Count++;
- return newNode;
- }
- /// <summary>
- /// Adds a item after a existing item on the list.
- /// </summary>
- /// <param name="node">Item on the list that will preceed the new item</param>
- /// <param name="newNode">Item to be added</param>
- /// <returns>New item</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public T AddAfter(T node, T newNode)
- {
- Debug.Assert(EqualsNull(newNode.ListPrevious));
- Debug.Assert(EqualsNull(newNode.ListNext));
- newNode.ListPrevious = node;
- newNode.ListNext = node.ListNext;
- node.ListNext = newNode;
- if (!EqualsNull(newNode.ListNext))
- {
- newNode.ListNext.ListPrevious = newNode;
- }
- if (Equals(Last, node))
- {
- Last = newNode;
- }
- Count++;
- return newNode;
- }
- /// <summary>
- /// Removes a item from the list.
- /// </summary>
- /// <param name="node">The item to be removed</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Remove(T node)
- {
- if (!EqualsNull(node.ListPrevious))
- {
- node.ListPrevious.ListNext = node.ListNext;
- }
- else
- {
- Debug.Assert(Equals(First, node));
- First = node.ListNext;
- }
- if (!EqualsNull(node.ListNext))
- {
- node.ListNext.ListPrevious = node.ListPrevious;
- }
- else
- {
- Debug.Assert(Equals(Last, node));
- Last = node.ListPrevious;
- }
- 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);
- }
- }
- }
|