コード例 #1
0
 /// <summary>
 /// Add a value after a given node.        
 /// Performance of <see cref="AddAfter"/> is O(1).
 /// <see cref="AddAfter"/> is not thread-safe for writing as we only expect a single writer/updater but is
 /// thead-safe for reading.
 /// 
 /// <example>
 /// Given two node [a] and [c] where [c] is after [a]. We want to add value "b" after [a].
 /// We therefore:
 /// 
 /// 1. Create [b] node and point to [c]  
 ///
 ///        [a]----->[c]
 ///            [b]---^
 /// 
 /// 2. Repoint [a] to point to [b]
 /// 
 ///        [a]       [c]
 ///         |-->[b]---^
 ///</example>
 /// </summary>
 /// <param name="node"></param>
 /// <param name="value"></param>
 /// <returns></returns>
 public ReadCopyUpdateListNode<T> AddAfter(ReadCopyUpdateListNode<T> node, T value)
 {
     if (node == null) throw new ArgumentNullException("node");
     ReadCopyUpdateListNode<T> newNode = new ReadCopyUpdateListNode<T>(value, node.next); // Create "b"
     node.next = newNode; // Repoint [a]
     return newNode;
 }
コード例 #2
0
        /// <summary>
        /// Remove a node.
        /// Performance of <see cref="Remove(ReadCopyUpdateListNode{T})"/> is O(n) since we have to find the 
        /// previous node in order to rejig the pointers.
        /// 
        /// Note that unlike classic RCU lists we don't have to "wait for readers" to finish before disposing
        /// of unused nodes - instead we simple remove the node and leave it to the garbage collector to clean up.
        /// 
        /// <example>
        /// Given that we have three nodes [a]->[b]->[c] and we want to remove [b] we just need to
        /// repoint [a]->[c], [b]->[c] still exists for current readers but it is no longer in the list and will 
        /// be garbage collected once it is no longer refereneced by and other code.
        /// </example>
        /// </summary>
        /// <param name="node"></param>
        public bool Remove(ReadCopyUpdateListNode<T> node)
        {
            if (node == null) throw new ArgumentNullException("node");
            ReadCopyUpdateListNode<T> local = head;
            if (local == null) 
                return false; // List is empty

            ReadCopyUpdateListNode<T> prev = null;
            if (local == node)
            {
                // we are removing the first node.
                head = node.next;
                return true; // head node removed
            }
            // Else we are removing some interior node
            // Find the node in the list
            while (local != null)
            {
                if (local.next == node)
                {
                    prev = local;
                    break;
                }
                local = local.next;
            }
            if (prev == null)
                return false; // node not in the list

            // All we need to do now is point the previous node to the next node.
            // node will be cleaned up by the garbage collector since it is no longer 
            // referenced by the list.
            prev.next = node.next;
            return true; // interior node removed.
        }
コード例 #3
0
 /// <summary>
 /// Find and remove a node with the value
 /// Performance of <see cref="Remove(T)"/> is O(n).
 /// </summary>
 /// <param name="value"></param>
 /// <returns>
 /// True if the node was removed, else False.
 /// </returns>
 public bool Remove(T value)
 {
     ReadCopyUpdateListNode<T> node = Find(value);
     if (node != null)
     {
         return Remove(node);
     }
     return false;
 }
コード例 #4
0
 /// <summary>
 /// Add a range of values.
 /// </summary>
 /// <param name="range"></param>
 public void AddRange(IEnumerable<T> range)
 {
     if (range == null) throw new ArgumentNullException("range");
     ReadCopyUpdateListNode<T> last = Last;
     foreach (T value in range)
     {
         last = (last == null) ? AddFirst(value) : AddAfter(last, value);
     }
 }
コード例 #5
0
            public bool MoveNext()
            {
                if (current == null)
                {
                    throw new InvalidOperationException("Cannot move past last node");
                }

                current = current.Next;
                return (current != null);
            }
コード例 #6
0
 /// <summary>
 /// Adds a value to the end of the list.
 /// Performance of <see cref="AddLast"/> is O(n).
 /// <see cref="AddLast"/> is not thread-safe for writing as we only expect a single writer/updater but is
 /// thead-safe for reading.
 /// </summary>
 /// <param name="value"></param>
 /// <returns>The value that was just added</returns>
 public ReadCopyUpdateListNode<T> AddLast(T value)
 {
     ReadCopyUpdateListNode<T> newNode = new ReadCopyUpdateListNode<T>(value);
     ReadCopyUpdateListNode<T> local = Last;
     if (local == null)
         head = newNode;
     else
         local.next = newNode;
     
     return newNode;
 }
コード例 #7
0
 /// <summary>
 /// Find the first node that matches the given <see cref="predicate"/> 
 /// </summary>
 /// <param name="predicate"></param>
 /// <returns></returns>
 public ReadCopyUpdateListNode<T> FindFirst(Predicate<T> predicate)
 {
     if (predicate == null) throw new ArgumentNullException("predicate");
     ReadCopyUpdateListNode<T> local = head;
     while (local != null)
     {
         if (predicate(local.Value))
             return local;
         local = local.next;
     }
     return null; // Not found
 }
コード例 #8
0
 /// <summary>
 /// Find the node with the value
 /// Performance of <see cref="Find"/> is O(n).
 /// </summary>
 /// <param name="value"></param>
 /// <returns></returns>
 public ReadCopyUpdateListNode<T> Find(T value)
 {
     EqualityComparer<T> comparer = EqualityComparer<T>.Default;
     ReadCopyUpdateListNode<T> local = head;
     while (local != null)
     {
         if (comparer.Equals(local.Value, value))
             return local;
         local = local.next;
     }
     return null; // Not found
 } 
コード例 #9
0
 /// <summary>
 /// Add a value to the beginning of the list.
 /// Performance of <see cref="AddFirst"/> is O(1).
 /// <see cref="AddFirst"/> is not thread-safe for writing as we only expect a single writer/updater but is
 /// thead-safe for reading.
 /// </summary>
 /// <param name="value"></param>
 /// <returns>The value that was just added</returns>
 public ReadCopyUpdateListNode<T> AddFirst(T value)
 {
     ReadCopyUpdateListNode<T> newNode = new ReadCopyUpdateListNode<T>(value);
     ReadCopyUpdateListNode<T> local = head;
     if (local == null) // List is currently empty
     {
         head = newNode;
     }
     else
     {
         newNode.next = head;
         head = newNode;
     }
     return newNode; // Publish new node.
 }
コード例 #10
0
 /// <summary>
 /// Create a node with a <see cref="value"/> pointing to another node.
 /// </summary>
 /// <param name="value"></param>
 /// <param name="next"></param>
 public ReadCopyUpdateListNode(T value, ReadCopyUpdateListNode<T> next)
 {
     this.value = value;
     this.next = next;
 }
コード例 #11
0
 public void Reset()
 {
     current = root;
 }
コード例 #12
0
 public ReadCopyUpdateListEnumerator(ReadCopyUpdateListNode<T> head)
 {
     // Create a root node representing the base of the enumerator pointing to the head of the list.
     root = new ReadCopyUpdateListNode<T>(default(T), head); 
     current = root;
 }
コード例 #13
0
 /// <summary>
 /// Clear the list
 /// Performance of <see cref="Clear"/> is O(1).
 /// </summary>
 public void Clear()
 {
     // Just reset the "head" to null. Existing reader will continue to work as normal.
     head = null;
 }