IntrusiveList.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. using System.Diagnostics;
  2. using System.Runtime.CompilerServices;
  3. namespace ARMeilleure.IntermediateRepresentation
  4. {
  5. /// <summary>
  6. /// Represents a efficient linked list that stores the pointer on the object directly and does not allocate.
  7. /// </summary>
  8. /// <typeparam name="T">Type of the list items</typeparam>
  9. class IntrusiveList<T> where T : class, IIntrusiveListNode<T>
  10. {
  11. /// <summary>
  12. /// First item of the list, or null if empty.
  13. /// </summary>
  14. public T First { get; private set; }
  15. /// <summary>
  16. /// Last item of the list, or null if empty.
  17. /// </summary>
  18. public T Last { get; private set; }
  19. /// <summary>
  20. /// Total number of items on the list.
  21. /// </summary>
  22. public int Count { get; private set; }
  23. /// <summary>
  24. /// Adds a item as the first item of the list.
  25. /// </summary>
  26. /// <param name="newNode">Item to be added</param>
  27. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  28. public void AddFirst(T newNode)
  29. {
  30. if (First != null)
  31. {
  32. AddBefore(First, newNode);
  33. }
  34. else
  35. {
  36. Debug.Assert(newNode.ListPrevious == null);
  37. Debug.Assert(newNode.ListNext == null);
  38. Debug.Assert(Last == null);
  39. First = newNode;
  40. Last = newNode;
  41. Debug.Assert(Count == 0);
  42. Count = 1;
  43. }
  44. }
  45. /// <summary>
  46. /// Adds a item as the last item of the list.
  47. /// </summary>
  48. /// <param name="newNode">Item to be added</param>
  49. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  50. public void AddLast(T newNode)
  51. {
  52. if (Last != null)
  53. {
  54. AddAfter(Last, newNode);
  55. }
  56. else
  57. {
  58. Debug.Assert(newNode.ListPrevious == null);
  59. Debug.Assert(newNode.ListNext == null);
  60. Debug.Assert(First == null);
  61. First = newNode;
  62. Last = newNode;
  63. Debug.Assert(Count == 0);
  64. Count = 1;
  65. }
  66. }
  67. /// <summary>
  68. /// Adds a item before a existing item on the list.
  69. /// </summary>
  70. /// <param name="node">Item on the list that will succeed the new item</param>
  71. /// <param name="newNode">Item to be added</param>
  72. /// <returns>New item</returns>
  73. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  74. public T AddBefore(T node, T newNode)
  75. {
  76. Debug.Assert(newNode.ListPrevious == null);
  77. Debug.Assert(newNode.ListNext == null);
  78. newNode.ListPrevious = node.ListPrevious;
  79. newNode.ListNext = node;
  80. node.ListPrevious = newNode;
  81. if (newNode.ListPrevious != null)
  82. {
  83. newNode.ListPrevious.ListNext = newNode;
  84. }
  85. if (First == node)
  86. {
  87. First = newNode;
  88. }
  89. Count++;
  90. return newNode;
  91. }
  92. /// <summary>
  93. /// Adds a item after a existing item on the list.
  94. /// </summary>
  95. /// <param name="node">Item on the list that will preceed the new item</param>
  96. /// <param name="newNode">Item to be added</param>
  97. /// <returns>New item</returns>
  98. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  99. public T AddAfter(T node, T newNode)
  100. {
  101. Debug.Assert(newNode.ListPrevious == null);
  102. Debug.Assert(newNode.ListNext == null);
  103. newNode.ListPrevious = node;
  104. newNode.ListNext = node.ListNext;
  105. node.ListNext = newNode;
  106. if (newNode.ListNext != null)
  107. {
  108. newNode.ListNext.ListPrevious = newNode;
  109. }
  110. if (Last == node)
  111. {
  112. Last = newNode;
  113. }
  114. Count++;
  115. return newNode;
  116. }
  117. /// <summary>
  118. /// Removes a item from the list.
  119. /// </summary>
  120. /// <param name="node">The item to be removed</param>
  121. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  122. public void Remove(T node)
  123. {
  124. if (node.ListPrevious != null)
  125. {
  126. node.ListPrevious.ListNext = node.ListNext;
  127. }
  128. else
  129. {
  130. Debug.Assert(First == node);
  131. First = node.ListNext;
  132. }
  133. if (node.ListNext != null)
  134. {
  135. node.ListNext.ListPrevious = node.ListPrevious;
  136. }
  137. else
  138. {
  139. Debug.Assert(Last == node);
  140. Last = node.ListPrevious;
  141. }
  142. node.ListPrevious = null;
  143. node.ListNext = null;
  144. Count--;
  145. }
  146. }
  147. }