Beispiel #1
0
        /// <summary>
        /// Pushes the specified node onto the top of the stack.
        /// </summary>
        /// <param name="node">The node to push onto the top of the stack.</param>
        /// <remarks>The specified node must NOT already be in another stack and must not be simultaneously added or removed by another thread.</remarks>
        public void Push(TYPE node)
        {
            Validate();
            // already in another list?
            if (node._nextNode != null)
            {
                Validate();
                throw new ApplicationException("The specified node is already in a list!");
            }
            // get the current top, which will be the old one if we succeed
            IntrusiveSinglyLinkedListNode oldTop = _root._nextNode;

            // loop until we win the race to insert us at the top
            do
            {
                // set this node's next node as the node we just got (we'll change it if we don't win the race)
                node._nextNode = oldTop;
                // race to place this node in as the top node--did we win?
                if (System.Threading.Interlocked.CompareExchange(ref _root._nextNode, node, oldTop) == oldTop)
                {
                    // increment the node count (it will be one off temporarily, but since the list can change at any time, nobody can reliably detect this anyway)
                    System.Threading.Interlocked.Increment(ref _count);
                    Validate();
                    return;
                }
                // else do it all again, get the current top, which will be the old one if we succeed
                oldTop = _root._nextNode;
            } while (true);
        }
Beispiel #2
0
        /// <summary>
        /// Pops off the top node on the stack and returns it.
        /// </summary>
        /// <returns>The top node, or <b>null</b> if there are no items in the stack.</returns>
        public TYPE Pop()
        {
            Validate();
            IntrusiveSinglyLinkedListNode ret;

            // wait until no other threads are popping
            while (System.Threading.Interlocked.CompareExchange(ref _popping, 1, 0) != 0)
            {
            }
            try
            {
                // loop while there something in the list to remove
                while ((ret = _root._nextNode) != _root)
                {
                    // get the new top
                    IntrusiveSinglyLinkedListNode newTop = ret._nextNode;
                    // another thread better not have already popped this node!
                    System.Diagnostics.Debug.Assert(newTop != null);
                    // try to exchange the new top into the top position--did we win the race against a pusher?
                    if (System.Threading.Interlocked.CompareExchange(ref _root._nextNode, newTop, ret) == ret)
                    {
                        // decrement the node count (it will be one off temporarily, but since the list can change at any time, nobody can reliably detect this anyway)
                        System.Threading.Interlocked.Decrement(ref _count);
                        // clear the next pointer because we are no longer in the list
                        ret._nextNode = null;
                        Validate();
                        // return the node that was removed
                        return((TYPE)ret);
                    }
                    // try again from the beginning
                }
            }
            finally
            {
                // we are no longer popping
                System.Threading.Interlocked.Exchange(ref _popping, 0);
            }
            Validate();
            // nothing there to pop!
            return(null);
        }
Beispiel #3
0
        private IntrusiveSinglyLinkedListNode _root; // we use a circular list instead of null because it allows us to detect if the node has been removed without traversing the entire list, because all removed nodes will have their next node set to null, while no nodes in the list will have their next node set to null.

        /// <summary>
        /// Constructs the list.
        /// </summary>
        public InterlockedStack()
        {
            _root           = new IntrusiveSinglyLinkedListNode();
            _root._nextNode = _root;
            Validate();
        }