コード例 #1
0
 private void printGivenLevel(RedBlackNode <TKey, TValue> node, int level)
 {
     if (node.IsSentinel)
     {
         Console.Write("null ");
         return;
     }
     if (level == 1)
     {
         Console.Write($"{node.Key} ");
     }
     else if (level > 1)
     {
         printGivenLevel(node.Left, level - 1);
         printGivenLevel(node.Right, level - 1);
     }
 }
コード例 #2
0
        private RedBlackNode <TKey, TValue> GetNode(TKey key)
        {
            // begin at root
            RedBlackNode <TKey, TValue> treeNode = _root;

            // traverse tree until node is found
            while (!treeNode.IsSentinel)
            {
                var result = key.CompareTo(treeNode.Key);
                if (result == 0)
                {
                    return(treeNode);
                }
                treeNode = result < 0
                    ? treeNode.Left
                    : treeNode.Right;
            }
            return(null);
        }
コード例 #3
0
        private void RotateRight(RedBlackNode <TKey, TValue> rotateNode)
        {
            var workNode = rotateNode.Left;

            rotateNode.Left = workNode.Right;

            if (!workNode.Right.IsSentinel)
            {
                workNode.Right.Parent = rotateNode;
            }

            if (!workNode.IsSentinel)
            {
                workNode.Parent = rotateNode.Parent;
            }

            if (rotateNode.Parent != _dummy)
            {
                if (rotateNode == rotateNode.Parent.Right)
                {
                    rotateNode.Parent.Right = workNode;
                }
                else
                {
                    rotateNode.Parent.Left = workNode;
                }
            }
            else
            {
                workNode.Parent = _dummy;
                _dummy.Left     = workNode;
                _root           = workNode;
            }

            workNode.Right = rotateNode;
            if (!rotateNode.IsSentinel)
            {
                rotateNode.Parent = workNode;
            }
        }
コード例 #4
0
        private static int MaxDepthInternal(RedBlackNode <TKey, TValue> node)
        {
            if (node.IsSentinel)
            {
                return(0);
            }
            else
            {
                /* compute the depth of each subtree */
                var lDepth = MaxDepthInternal(node.Left);
                var rDepth = MaxDepthInternal(node.Right);

                /* use the larger one */
                if (lDepth > rDepth)
                {
                    return(lDepth + 1);
                }
                else
                {
                    return(rDepth + 1);
                }
            }
        }
コード例 #5
0
        private bool setMarker(
            List <RedBlackNode <TKey, TValue> > nodesToMark,
            Guid pid,
            RedBlackNode <TKey, TValue> z = null)
        {
            var nodesToUnMark = new List <RedBlackNode <TKey, TValue> >();

            RedBlackNode <TKey, TValue> node;

            for (var i = 0; i < 3; i++)
            {
                node = nodesToMark[i];
                if (!SpacingRuleIsSatisfied(node, pid, true, z))
                {
                    foreach (var n in nodesToUnMark)
                    {
                        n.Marker = Guid.Empty;
                    }
                    return(false);
                }
                node.Marker = pid;
                nodesToUnMark.Add(node);
            }

            node = nodesToMark[3];
            if (!SpacingRuleIsSatisfied(node, pid, false, z))
            {
                foreach (var n in nodesToUnMark)
                {
                    n.Marker = Guid.Empty;
                }
                return(false);
            }
            node.Marker = pid;

            return(true);
        }
コード例 #6
0
        private bool IsIn(RedBlackNode <TKey, TValue> node, Guid pid)
        {
            List <MoveUpStruct <TKey, TValue> > moveUpStructList;

            if (moveUpStructDict.ContainsKey(pid))
            {
                moveUpStructList = moveUpStructDict[pid];
            }
            else
            {
                return(false);
            }
            var moveUpStruct = moveUpStructList[moveUpStructList.Count - 1];

            foreach (var n in moveUpStruct.Nodes)
            {
                if (node == n)
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #7
0
 private void BalanceTreeAfterDelete(RedBlackNode <TKey, TValue> linkedNode)
 {
     // maintain Red-Black tree balance after deleting node
     while (linkedNode != _root && linkedNode.Color == RedBlackNodeType.Black)
     {
         RedBlackNode <TKey, TValue> workNode;
         // determine sub tree from parent
         if (linkedNode == linkedNode.Parent.Left)
         {
             // y is x's sibling
             workNode = linkedNode.Parent.Right;
             if (workNode.Color == RedBlackNodeType.Red)
             {
                 // x is black, y is red - make both black and rotate
                 linkedNode.Parent.Color = RedBlackNodeType.Red;
                 workNode.Color          = RedBlackNodeType.Black;
                 RotateLeft(linkedNode.Parent);
                 workNode = linkedNode.Parent.Right;
             }
             if (workNode.Left.Color == RedBlackNodeType.Black &&
                 workNode.Right.Color == RedBlackNodeType.Black)
             {
                 // children are both black
                 // change parent to red
                 workNode.Color = RedBlackNodeType.Red;
                 // move up the tree
                 linkedNode = linkedNode.Parent;
             }
             else
             {
                 if (workNode.Right.Color == RedBlackNodeType.Black)
                 {
                     workNode.Left.Color = RedBlackNodeType.Black;
                     workNode.Color      = RedBlackNodeType.Red;
                     RotateRight(workNode);
                     workNode = linkedNode.Parent.Right;
                 }
                 linkedNode.Parent.Color = RedBlackNodeType.Black;
                 workNode.Color          = linkedNode.Parent.Color;
                 workNode.Right.Color    = RedBlackNodeType.Black;
                 RotateLeft(linkedNode.Parent);
                 linkedNode = _root;
             }
         }
         else
         {       // right subtree - same as code above with right and left swapped
             workNode = linkedNode.Parent.Left;
             if (workNode.Color == RedBlackNodeType.Red)
             {
                 linkedNode.Parent.Color = RedBlackNodeType.Red;
                 workNode.Color          = RedBlackNodeType.Black;
                 RotateRight(linkedNode.Parent);
                 workNode = linkedNode.Parent.Left;
             }
             if (workNode.Right.Color == RedBlackNodeType.Black &&
                 workNode.Left.Color == RedBlackNodeType.Black)
             {
                 workNode.Color = RedBlackNodeType.Red;
                 linkedNode     = linkedNode.Parent;
             }
             else
             {
                 if (workNode.Left.Color == RedBlackNodeType.Black)
                 {
                     workNode.Right.Color = RedBlackNodeType.Black;
                     workNode.Color       = RedBlackNodeType.Red;
                     RotateLeft(workNode);
                     workNode = linkedNode.Parent.Left;
                 }
                 workNode.Color          = linkedNode.Parent.Color;
                 linkedNode.Parent.Color = RedBlackNodeType.Black;
                 workNode.Left.Color     = RedBlackNodeType.Black;
                 RotateRight(linkedNode.Parent);
                 linkedNode = _root;
             }
         }
     }
     linkedNode.Color = RedBlackNodeType.Black;
 }
コード例 #8
0
        private void Delete(RedBlackNode <TKey, TValue> deleteNode)
        {
            // A node to be deleted will be:
            //		1. a leaf with no children
            //		2. have one child
            //		3. have two children
            // If the deleted node is red, the red black properties still hold.
            // If the deleted node is black, the tree needs rebalancing

            // work node
            RedBlackNode <TKey, TValue> workNode;

            // find the replacement node (the successor to x) - the node one with
            // at *most* one child.
            if (deleteNode.Left.IsSentinel || deleteNode.Right.IsSentinel)
            {
                // node has sentinel as a child
                workNode = deleteNode;
            }
            else
            {
                // z has two children, find replacement node which will
                // be the leftmost node greater than z
                // traverse right subtree
                workNode = deleteNode.Right;
                // to find next node in sequence
                while (!workNode.Left.IsSentinel)
                {
                    workNode = workNode.Left;
                }
            }

            // at this point, y contains the replacement node. it's content will be copied
            // to the valules in the node to be deleted

            // x (y's only child) is the node that will be linked to y's old parent.
            RedBlackNode <TKey, TValue> linkedNode = !workNode.Left.IsSentinel
                                                 ? workNode.Left
                                                 : workNode.Right;

            // replace x's parent with y's parent and
            // link x to proper subtree in parent
            // this removes y from the chain
            linkedNode.Parent = workNode.Parent;
            if (workNode.Parent != null)
            {
                if (workNode == workNode.Parent.Left)
                {
                    workNode.Parent.Left = linkedNode;
                }
                else
                {
                    workNode.Parent.Right = linkedNode;
                }
            }
            else
            {
                // make x the root node
                _root = linkedNode;
            }

            // copy the values from y (the replacement node) to the node being deleted.
            // note: this effectively deletes the node.
            if (workNode != deleteNode)
            {
                deleteNode.Key  = workNode.Key;
                deleteNode.Data = workNode.Data;
            }

            if (workNode.Color == RedBlackNodeType.Black)
            {
                BalanceTreeAfterDelete(linkedNode);
            }
        }
コード例 #9
0
        private void BalanceTreeAfterInsert(RedBlackNode <TKey, TValue> insertedNode, List <RedBlackNode <TKey, TValue> > working)
        {
            // maintain red-black tree properties after adding newNode
            while (insertedNode != _root && insertedNode.Parent.Color == RedBlackNodeType.Red)
            {
                RedBlackNode <TKey, TValue> workNode;
                if (insertedNode.Parent == insertedNode.Parent.Parent.Left)
                {
                    workNode = insertedNode.Parent.Parent.Right;
                    if (workNode != null && workNode.Color == RedBlackNodeType.Red)
                    {
                        insertedNode.Parent.Color = RedBlackNodeType.Black;
                        workNode.Color            = RedBlackNodeType.Black;

                        insertedNode.Parent.Parent.Color = RedBlackNodeType.Red;

                        // continue loop with grandparent
                        insertedNode = insertedNode.Parent.Parent;
                        if (insertedNode == _root || insertedNode.Parent.Color != RedBlackNodeType.Red)
                        {
                            break;
                        }
                        MoveLocalAreaUpward(insertedNode, working);
                    }
                    else
                    {
                        if (insertedNode == insertedNode.Parent.Right)
                        {
                            insertedNode = insertedNode.Parent;
                            RotateLeft(insertedNode);
                        }
                        insertedNode.Parent.Color        = RedBlackNodeType.Black;
                        insertedNode.Parent.Parent.Color = RedBlackNodeType.Red;
                        RotateRight(insertedNode.Parent.Parent);
                    }
                }
                else
                {
                    workNode = insertedNode.Parent.Parent.Left;
                    if (workNode != null && workNode.Color == RedBlackNodeType.Red)
                    {
                        insertedNode.Parent.Color        = RedBlackNodeType.Black;
                        workNode.Color                   = RedBlackNodeType.Black;
                        insertedNode.Parent.Parent.Color = RedBlackNodeType.Red;

                        // continue loop with grandparent
                        insertedNode = insertedNode.Parent.Parent;
                        if (insertedNode == _root || insertedNode.Parent.Color != RedBlackNodeType.Red)
                        {
                            break;
                        }
                        MoveLocalAreaUpward(insertedNode, working);
                    }
                    else
                    {
                        if (insertedNode == insertedNode.Parent.Left)
                        {
                            insertedNode = insertedNode.Parent;
                            RotateRight(insertedNode);
                        }
                        insertedNode.Parent.Color        = RedBlackNodeType.Black;
                        insertedNode.Parent.Parent.Color = RedBlackNodeType.Red;
                        RotateLeft(insertedNode.Parent.Parent);
                    }
                }
            }
            _root.Color = RedBlackNodeType.Black;
        }
コード例 #10
0
        private (RedBlackNode <TKey, TValue>, bool) Insert(RedBlackNode <TKey, TValue> newNode)
        {
            RedBlackNode <TKey, TValue> aLocked;

            RedBlackNode <TKey, TValue> lastBlack = null;

            Monitor.Enter(rootLock);
            RedBlackNode <TKey, TValue> workNode = _root;

            workNode.GetALock();

            if (workNode.IsSentinel)
            {
                // workNode is root
                _root = newNode;
                _root.GetALock();
                workNode.ReleaseALock();
                return(_root, true);
            }

            bool releaseRoot = true;

            aLocked = workNode;

            while (true)
            {
                if (workNode.IsSentinel)
                {
                    break;
                }

                // find Parent
                newNode.Parent = workNode;
                int result = newNode.Key.CompareTo(workNode.Key);
                if (result == 0)
                {
                    throw new Exception("duplicate key");
                }

                if (workNode.Color == RedBlackNodeType.Black && lastBlack != _root)
                {
                    if (lastBlack != null)
                    {
                        lastBlack.GetALock();
                        aLocked.ReleaseALock();
                        if (releaseRoot)
                        {
                            Monitor.Exit(rootLock);
                        }
                        aLocked     = lastBlack;
                        releaseRoot = false;
                    }
                    lastBlack = workNode;
                }
                else
                {
                    if (workNode.Color == RedBlackNodeType.Black)
                    {
                        lastBlack = workNode;
                    }
                    else
                    {
                        lastBlack = null;
                    }
                }

                if (result > 0)
                {
                    workNode = workNode.Right;
                }
                else
                {
                    workNode = workNode.Left;
                }
            }

            if (newNode.Key.CompareTo(newNode.Parent.Key) > 0)
            {
                newNode.Parent.Right = newNode;
            }
            else
            {
                newNode.Parent.Left = newNode;
            }

            return(aLocked, releaseRoot);
        }
コード例 #11
0
        private void FixUpCase1(
            RedBlackNode <TKey, TValue>[] localArea,
            Guid pid)
        {
            //  correct relocated intention markers for other processes
            if (localArea[2].Marker != Guid.Empty &&
                localArea[3].Marker == localArea[2].Marker &&
                localArea[1].Marker == Guid.Empty)
            {
                localArea[1].Marker = localArea[2].Marker;
                localArea[2].Marker = Guid.Empty;
            }
            if (localArea[2].Marker != Guid.Empty &&
                localArea[4].Marker == localArea[2].Marker &&
                localArea[1].Marker == localArea[2].Marker)
            {
                Console.WriteLine("FixUpCase1: This should not happen!");
            }

            // Now correct local area and intention markers for the given process
            // release highest held intention marker (fifth intention marker)
            var intentionMarkers = new RedBlackNode <TKey, TValue> [4];

            while (true)
            {
                if (GetFlagsForMarkers(localArea[2], pid, intentionMarkers, null))
                {
                    break;
                }
            }
            intentionMarkers[3].Marker = Guid.Empty;
            ReleaseFlags(pid, false, intentionMarkers.ToList());

            //  release flag on node not "moved"
            localArea[4].FreeNodeAtomically();
            // acquire marker on old sibling of x and free the flag
            localArea[2].Marker = pid;
            localArea[2].FreeNodeAtomically();

            RedBlackNode <TKey, TValue> neww  = localArea[3];
            RedBlackNode <TKey, TValue> newwl = neww.Left;
            RedBlackNode <TKey, TValue> newwr = neww.Right;

            if (!IsIn(newwl, pid))
            {
                while (true)
                {
                    if (newwl.OccupyNodeAtomically())
                    {
                        break;
                    }
                }
            }
            if (!IsIn(newwr, pid))
            {
                while (true)
                {
                    if (newwr.OccupyNodeAtomically())
                    {
                        break;
                    }
                }
            }

            localArea[2] = neww;
            if (neww == localArea[1].Right)
            {
                localArea[3] = newwl;
                localArea[4] = newwr;
            }
            else
            {
                localArea[3] = newwr;
                localArea[4] = newwl;
            }
        }
コード例 #12
0
        private bool SpacingRuleIsSatisfied(
            RedBlackNode <TKey, TValue> t,
            Guid pid,
            bool isParentOccupied,
            RedBlackNode <TKey, TValue> z = null)
        {
            // we already hold flags on both t and z.
            bool isMarkerAllowed = true;

            // check that t has no marker set
            if (z == null || z != t)
            {
                if (t.Marker != Guid.Empty)
                {
                    return(false);
                }
            }

            // check that t's parent has no flag or marker
            RedBlackNode <TKey, TValue> tp = t.Parent;

            if (z == null || z != tp)
            {
                if (!isParentOccupied)
                {
                    if (!IsIn(tp, pid) && !tp.OccupyNodeAtomically())
                    {
                        return(false);
                    }
                    // verify parent is unchanged
                    if (tp != t.Parent)
                    {
                        tp.FreeNodeAtomically();
                        return(false);
                    }
                }

                if (tp.Marker != Guid.Empty)
                {
                    if (!isParentOccupied)
                    {
                        tp.FreeNodeAtomically();
                    }
                    return(false);
                }
            }

            //check that t's sibling has no flag or marker or PIDtoIgnore
            var nodesToRelease = new List <RedBlackNode <TKey, TValue> >();
            var ts             = (t == tp.Left ? tp.Right : tp.Left);

            if (!IsIn(ts, pid) && !ts.OccupyNodeAtomically())
            {
                if (z == null || z != tp)
                {
                    if (!isParentOccupied)
                    {
                        nodesToRelease.Add(tp);
                        ReleaseFlags(pid, false, nodesToRelease);
                    }
                }
                return(false);
            }

            Guid PIDtoIgnore;
            bool IsTooCloseProcess = getPIDtoIgnore(pid, out PIDtoIgnore);

            if (ts.Marker != Guid.Empty && (!IsTooCloseProcess || ts.Marker != PIDtoIgnore))
            {
                isMarkerAllowed = false;
            }

            // release flags on ts and tp
            nodesToRelease.Add(ts);
            if (z == null || z != tp)
            {
                if (!isParentOccupied)
                {
                    nodesToRelease.Add(tp);
                }
            }
            ReleaseFlags(pid, false, nodesToRelease);

            return(isMarkerAllowed);
        }
コード例 #13
0
        private RedBlackNode <TKey, TValue> MoveDeleterUp(
            RedBlackNode <TKey, TValue>[] localArea,
            Guid pid)
        {
            // Check for a moveUpStruct from another process (due to Move-Up rule). Get direct pointers

            // get  old local area
            RedBlackNode <TKey, TValue> oldx   = localArea[0];
            RedBlackNode <TKey, TValue> oldp   = localArea[1];
            RedBlackNode <TKey, TValue> oldw   = localArea[2];
            RedBlackNode <TKey, TValue> oldwlc = localArea[3];
            RedBlackNode <TKey, TValue> oldwrc = localArea[4];

            var newx = oldp;

            localArea[0] = newx;

            // Extend intention markers (getting flags to set them) by one more
            // Also convert marker on oldgp to a flag i.e. set localArea[1] to oldgp
            while (true)
            {
                if (GetFlagsAndMarkersAbove(oldp, localArea, pid, 1))
                {
                    break;
                }
            }

            // get flags on rest of the new local area (w, wlc, wrc)
            var newp = newx.Parent;
            var neww = newx == newp.Left ? newp.Right : newp.Left;

            if (!IsIn(neww, pid))
            {
                while (true)
                {
                    if (neww.OccupyNodeAtomically())
                    {
                        break;
                    }
                }
            }

            var newwlc = neww.Left;
            var newwrc = neww.Right;

            if (!IsIn(newwlc, pid))
            {
                while (true)
                {
                    if (newwlc.OccupyNodeAtomically())
                    {
                        break;
                    }
                }
            }
            if (!IsIn(newwrc, pid))
            {
                while (true)
                {
                    if (newwrc.OccupyNodeAtomically())
                    {
                        break;
                    }
                }
            }

            localArea[2] = neww;
            if (neww == localArea[1].Right)
            {
                localArea[3] = newwlc;
                localArea[4] = newwrc;
            }
            else
            {
                localArea[3] = newwrc;
                localArea[4] = newwlc;
            }

            // release flag on old local area
            List <RedBlackNode <TKey, TValue> > nodesToRelease = new List <RedBlackNode <TKey, TValue> >();

            nodesToRelease.Add(oldx);
            nodesToRelease.Add(oldw);
            nodesToRelease.Add(oldwlc);
            nodesToRelease.Add(oldwrc);
            ReleaseFlags(pid, true, nodesToRelease);

            return(newx);
        }
コード例 #14
0
        private bool GetFlagsAndMarkersAbove(
            RedBlackNode <TKey, TValue> start,
            RedBlackNode <TKey, TValue>[] localArea,
            Guid pid,
            int numAdditional,
            RedBlackNode <TKey, TValue> z = null)
        {
            var markerPositions = new RedBlackNode <TKey, TValue> [4];

            if (!GetFlagsForMarkers(start, pid, markerPositions, z))
            {
                return(false);
            }

            if (numAdditional == 0)
            {
                bool IsSetMarkerSuccess = setMarker(markerPositions.ToList(), pid, z);

                // release flags on four nodes after putting markers
                ReleaseFlags(pid, false, markerPositions.ToList());

                return(IsSetMarkerSuccess);
            }

            var nodesToRelease = new List <RedBlackNode <TKey, TValue> >();

            // get additional marker(s) above
            RedBlackNode <TKey, TValue> firstnew = markerPositions[3].Parent;

            if (!IsIn(firstnew, pid) && !firstnew.OccupyNodeAtomically())
            {
                nodesToRelease.Add(markerPositions[0]);
                nodesToRelease.Add(markerPositions[1]);
                nodesToRelease.Add(markerPositions[2]);
                nodesToRelease.Add(markerPositions[3]);
                ReleaseFlags(pid, false, nodesToRelease.ToList());
                return(false);
            }
            if (firstnew != markerPositions[3].Parent && !SpacingRuleIsSatisfied(firstnew, pid, false, null))
            {
                nodesToRelease.Add(markerPositions[0]);
                nodesToRelease.Add(markerPositions[1]);
                nodesToRelease.Add(markerPositions[2]);
                nodesToRelease.Add(markerPositions[3]);
                nodesToRelease.Add(firstnew);
                ReleaseFlags(pid, false, nodesToRelease.ToList());
                return(false);
            }

            if (numAdditional == 1)
            {
                firstnew.Marker = pid;
                nodesToRelease.Add(markerPositions[1]);
                nodesToRelease.Add(markerPositions[2]);
                nodesToRelease.Add(markerPositions[3]);
                nodesToRelease.Add(firstnew);

                localArea[1] = markerPositions[0];
                markerPositions[0].Marker = Guid.Empty;

                ReleaseFlags(pid, true, nodesToRelease);

                return(true);;
            }

            if (numAdditional == 2)
            {
                // get additional marker above
                RedBlackNode <TKey, TValue> secondnew = firstnew.Parent;

                if (!IsIn(secondnew, pid) && !secondnew.OccupyNodeAtomically())
                {
                    nodesToRelease.Add(markerPositions[0]);
                    nodesToRelease.Add(markerPositions[1]);
                    nodesToRelease.Add(markerPositions[2]);
                    nodesToRelease.Add(markerPositions[3]);
                    nodesToRelease.Add(firstnew);
                    ReleaseFlags(pid, false, nodesToRelease.ToList());
                    return(false);
                }
                if (secondnew != firstnew.Parent && !SpacingRuleIsSatisfied(secondnew, pid, false, null))
                {
                    nodesToRelease.Add(markerPositions[0]);
                    nodesToRelease.Add(markerPositions[1]);
                    nodesToRelease.Add(markerPositions[2]);
                    nodesToRelease.Add(markerPositions[3]);
                    nodesToRelease.Add(firstnew);
                    nodesToRelease.Add(secondnew);
                    ReleaseFlags(pid, false, nodesToRelease.ToList());
                    return(false);
                }
                firstnew.Marker  = pid;
                secondnew.Marker = pid;

                nodesToRelease.Add(markerPositions[2]);
                nodesToRelease.Add(markerPositions[3]);
                nodesToRelease.Add(firstnew);
                nodesToRelease.Add(secondnew);

                markerPositions[0].Marker = Guid.Empty;
                markerPositions[1].Marker = Guid.Empty;

                ReleaseFlags(pid, true, nodesToRelease);

                return(true);;
            }

            return(true);
        }
コード例 #15
0
        public RedBlackNode <TKey, TValue> Search(TKey key)
        {
            while (true)
            {
                if (_root == null)
                {
                    break;
                }

                // begin at root
                RedBlackNode <TKey, TValue> workNode = _root, nextNode = _root;

                while (true)
                {
                    if (!workNode.OccupyNodeAtomically())
                    {
                        continue;
                    }

                    int result = key.CompareTo(workNode.Key);
                    if (result == 0)
                    {
                        return(workNode);
                    }

                    if (result > 0)
                    {
                        nextNode = workNode.Right;
                    }
                    else
                    {
                        nextNode = workNode.Left;
                    }

                    if (nextNode.IsSentinel)
                    {
                        break;
                    }

                    if (!nextNode.OccupyNodeAtomically())
                    {
                        workNode.FreeNodeAtomically();
                        break;
                    }

                    if (nextNode.Parent != workNode)
                    {
                        workNode.FreeNodeAtomically();
                        nextNode.FreeNodeAtomically();
                        continue;
                    }

                    workNode.FreeNodeAtomically();
                    workNode = nextNode;
                }

                if (nextNode.IsSentinel)
                {
                    break;
                }
            }

            return(null);
        }
コード例 #16
0
        private void BalanceTreeAfterDelete(
            RedBlackNode <TKey, TValue> x,
            RedBlackNode <TKey, TValue>[] localArea,
            Guid pid)
        {
            bool done = false, didMoveUp = false;

            // maintain Red-Black tree balance after deleting node
            while (x != _root && x.Color == RedBlackNodeType.Black && !done)
            {
                RedBlackNode <TKey, TValue> w;
                // determine sub tree from parent
                if (x == x.Parent.Left)
                {
                    w = x.Parent.Right;
                    if (w.Color == RedBlackNodeType.Red)
                    {
                        x.Parent.Color = RedBlackNodeType.Red;
                        w.Color        = RedBlackNodeType.Black;
                        RotateLeft(x.Parent);
                        w = x.Parent.Right;
                        FixUpCase1(localArea, pid);
                    }
                    if (w.Left.Color == RedBlackNodeType.Black &&
                        w.Right.Color == RedBlackNodeType.Black)
                    {
                        // children are both black
                        // change parent to red
                        w.Color = RedBlackNodeType.Red;
                        // move up the tree
                        x = MoveDeleterUp(localArea, pid);
                    }
                    else
                    {
                        if (w.Right.Color == RedBlackNodeType.Black)
                        {
                            w.Left.Color = RedBlackNodeType.Black;
                            w.Color      = RedBlackNodeType.Red;
                            RotateRight(w);
                            FixUpCase3(localArea, pid);
                            w = x.Parent.Right;
                        }
                        w.Color        = x.Parent.Color;
                        x.Parent.Color = RedBlackNodeType.Black;
                        w.Right.Color  = RedBlackNodeType.Black;
                        RotateLeft(x.Parent);
                        didMoveUp = ApplyMoveUpRule(localArea, pid);
                        done      = true;
                    }
                }
                else
                {       // right subtree - same as code above with right and left swapped
                    w = x.Parent.Left;
                    if (w.Color == RedBlackNodeType.Red)
                    {
                        x.Parent.Color = RedBlackNodeType.Red;
                        w.Color        = RedBlackNodeType.Black;
                        RotateRight(x.Parent);
                        w = x.Parent.Left;
                        FixUpCase1(localArea, pid);
                    }
                    if (w.Right.Color == RedBlackNodeType.Black &&
                        w.Left.Color == RedBlackNodeType.Black)
                    {
                        w.Color = RedBlackNodeType.Red;
                        x       = MoveDeleterUp(localArea, pid);
                    }
                    else
                    {
                        if (w.Left.Color == RedBlackNodeType.Black)
                        {
                            w.Right.Color = RedBlackNodeType.Black;
                            w.Color       = RedBlackNodeType.Red;
                            RotateLeft(w);
                            FixUpCase3(localArea, pid);
                            w = x.Parent.Left;
                        }
                        w.Color        = x.Parent.Color;
                        x.Parent.Color = RedBlackNodeType.Black;
                        w.Left.Color   = RedBlackNodeType.Black;
                        RotateRight(x.Parent);
                        didMoveUp = ApplyMoveUpRule(localArea, pid);
                        done      = true;
                    }
                }
            }
            if (!didMoveUp)
            {
                x.Color = RedBlackNodeType.Black;

                //  release markers on local area
                var intentionMarkers = new RedBlackNode <TKey, TValue> [4];
                var localAreaTopNode = (localArea[1].Parent == localArea[2]) ? localArea[2] : localArea[1];
                while (true)
                {
                    if (GetFlagsForMarkers(localAreaTopNode, pid, intentionMarkers, null))
                    {
                        break;
                    }
                }
                foreach (var node in intentionMarkers)
                {
                    node.Marker = Guid.Empty;
                }
                ReleaseFlags(pid, false, intentionMarkers.ToList());

                //  correct relocated intention markers for other processes
                if (localArea[2].Marker != Guid.Empty &&
                    localArea[3].Marker == localArea[2].Marker &&
                    localArea[1].Marker == Guid.Empty)
                {
                    localArea[1].Marker = localArea[2].Marker;
                    localArea[2].Marker = Guid.Empty;
                }
                if (localArea[2].Marker != Guid.Empty &&
                    localArea[4].Marker == localArea[2].Marker &&
                    localArea[1].Marker == localArea[2].Marker)
                {
                    Console.WriteLine("FixUpCase4: This should not happen!");
                    while (true)
                    {
                        if (localArea[2].Parent.OccupyNodeAtomically())
                        {
                            break;
                        }
                    }
                    localArea[2].Parent.Marker = localArea[2].Marker;
                    localArea[2].Parent.FreeNodeAtomically();
                }

                //  release flags on local area
                foreach (var node in localArea)
                {
                    node?.FreeNodeAtomically();
                }
            }
        }
コード例 #17
0
        private bool SetupLocalAreaForDelete(
            RedBlackNode <TKey, TValue> y,
            RedBlackNode <TKey, TValue>[] localArea,
            Guid pid,
            RedBlackNode <TKey, TValue> z = null)
        {
            var x = y.Left.IsSentinel ? y.Right : y.Left;

            // occupy the node which will replace y
            if (!x.OccupyNodeAtomically())
            {
                return(false);
            }
            localArea[0] = x;

            var  yp          = y.Parent;
            bool isNotCheckZ = (z == null || yp != z);

            if (isNotCheckZ && !yp.OccupyNodeAtomically())
            {
                x.FreeNodeAtomically();
                return(false);
            }

            // verify that parent is unchanged
            if (yp != y.Parent)
            {
                x.FreeNodeAtomically();
                if (isNotCheckZ)
                {
                    yp.FreeNodeAtomically();
                }
                return(false);
            }
            localArea[1] = yp;

            var w = (y == yp.Left ? yp.Right : yp.Left);

            if (!w.OccupyNodeAtomically())
            {
                x.FreeNodeAtomically();
                if (isNotCheckZ)
                {
                    yp.FreeNodeAtomically();
                }
                return(false);
            }

            // verify if sibling is changed
            var nw = (y == yp.Left ? yp.Right : yp.Left);

            if (w != nw)
            {
                x.FreeNodeAtomically();
                w.FreeNodeAtomically();
                if (isNotCheckZ)
                {
                    yp.FreeNodeAtomically();
                }
                return(false);
            }
            localArea[2] = w;

            var wlc = w.Left;
            var wrc = w.Right;

            if (!w.IsSentinel)
            {
                if (!wlc.OccupyNodeAtomically())
                {
                    x.FreeNodeAtomically();
                    w.FreeNodeAtomically();
                    if (isNotCheckZ)
                    {
                        yp.FreeNodeAtomically();
                    }
                    return(false);
                }

                // validate
                if (w.Left != wlc)
                {
                    x.FreeNodeAtomically();
                    w.FreeNodeAtomically();
                    wlc.FreeNodeAtomically();
                    if (isNotCheckZ)
                    {
                        yp.FreeNodeAtomically();
                    }
                    return(false);
                }

                if (!wrc.OccupyNodeAtomically())
                {
                    x.FreeNodeAtomically();
                    w.FreeNodeAtomically();
                    wlc.FreeNodeAtomically();
                    if (isNotCheckZ)
                    {
                        yp.FreeNodeAtomically();
                    }
                    return(false);
                }

                // validate
                if (w.Right != wrc)
                {
                    x.FreeNodeAtomically();
                    w.FreeNodeAtomically();
                    wlc.FreeNodeAtomically();
                    wrc.FreeNodeAtomically();
                    if (isNotCheckZ)
                    {
                        yp.FreeNodeAtomically();
                    }
                    return(false);
                }

                if (w == yp.Right)
                {
                    localArea[3] = wlc;
                    localArea[4] = wrc;
                }
                else
                {
                    localArea[3] = wrc;
                    localArea[4] = wlc;
                }
            }

            if (!GetFlagsAndMarkersAbove(yp, localArea, pid, 0, z))
            {
                x.FreeNodeAtomically();
                w.FreeNodeAtomically();
                if (!w.IsSentinel)
                {
                    wlc.FreeNodeAtomically();
                    wrc.FreeNodeAtomically();
                }
                if (isNotCheckZ)
                {
                    yp.FreeNodeAtomically();
                }
                return(false);
            }
            return(true);
        }
コード例 #18
0
        private bool ApplyMoveUpRule(
            RedBlackNode <TKey, TValue>[] localArea,
            Guid pid)
        {
            // Check in our local area to see if two processes beneath
            // use have been brought too close together by our rotations.
            // The three cases correspond to Figures 17, 18 and 19.
            var w         = localArea[4];
            var wChild_p1 = w.Right;
            var wChild_p2 = w.Left;

            if (w == w.Parent.Left)
            {
                wChild_p1 = w.Left;
                wChild_p2 = w.Right;
            }

            var case1 = w.Marker == w.Parent.Marker &&
                        w.Marker == wChild_p1.Marker &&
                        w.Marker != Guid.Empty &&
                        wChild_p2.Marker != Guid.Empty;

            var case2 = wChild_p1.Marker == w.Marker &&
                        w.Marker != Guid.Empty &&
                        wChild_p2.Marker != Guid.Empty;

            var case3 = w.Marker == Guid.Empty &&
                        wChild_p1.Marker != Guid.Empty &&
                        wChild_p2.Marker != Guid.Empty;

            if (case1 || case2 || case3)
            {
                Console.WriteLine("case1 || case2 || case3");
                // Let pid release their markers ??????????? or pass their markers as well?????
                var intentionMarkers = new RedBlackNode <TKey, TValue> [4];
                while (true)
                {
                    if (GetFlagsForMarkers(w.Parent, pid, intentionMarkers, null))
                    {
                        break;
                    }
                }
                foreach (var node in intentionMarkers)
                {
                    node.Marker = Guid.Empty;
                }
                ReleaseFlags(pid, false, intentionMarkers.ToList());

                // Build structure listing the nodes we hold flags on
                // (moveUpStruct) and specifying the PID of the other
                // "too-close" process (marker[left[w]) and the goal (GP).
                // Make structure available to process id: marker[right[w]]

                var newMoveUpStruct = new MoveUpStruct <TKey, TValue>();
                newMoveUpStruct.Nodes.Add(localArea[0]);
                newMoveUpStruct.Nodes.Add(localArea[1]);
                newMoveUpStruct.Nodes.Add(localArea[2]);    // top node
                newMoveUpStruct.Nodes.Add(localArea[3]);
                newMoveUpStruct.Nodes.Add(localArea[4]);
                newMoveUpStruct.PidToIgnore = wChild_p2.Marker;
                // newMoveUpStruct.Gp = w.Parent.Parent ???????????? Gp is not locked, what if it changes

                var inheritedMoveUpStructs = new List <MoveUpStruct <TKey, TValue> >();

                if (moveUpStructDict.ContainsKey(pid))
                {
                    inheritedMoveUpStructs = moveUpStructDict[pid];
                }
                inheritedMoveUpStructs.Add(newMoveUpStruct);

                moveUpStructDict.TryAdd(wChild_p1.Marker, inheritedMoveUpStructs);
            }
            return(false);
        }
コード例 #19
0
        private bool OccupyLocalAreaForInsert(RedBlackNode <TKey, TValue> node, RedBlackNode <TKey, TValue>[] localArea, Guid pid)
        {
            // occupy the node to be inserted
            if (!node.OccupyNodeAtomically())
            {
                node.Parent.FreeNodeAtomically();
                return(false);
            }

            var grandParent = node.Parent.Parent;

            // occupy grandparent
            if (!grandParent.OccupyNodeAtomically())
            {
                node.Parent.FreeNodeAtomically();
                node.FreeNodeAtomically();
                return(false);
            }

            // if grand parent changed before occupying, return false
            if (grandParent != node.Parent.Parent)
            {
                // free grand parent
                grandParent.FreeNodeAtomically();
                node.Parent.FreeNodeAtomically();
                node.FreeNodeAtomically();
                return(false);
            }

            var uncle = grandParent.Left == node.Parent ? grandParent.Right : grandParent.Left;

            if (!uncle.OccupyNodeAtomically())
            {
                grandParent.FreeNodeAtomically();
                node.Parent.FreeNodeAtomically();
                node.FreeNodeAtomically();
                return(false);
            }

            //check if uncle is not changed
            var temp_uncle = (grandParent.Left == node.Parent ? grandParent.Right : grandParent.Left);

            if (uncle != temp_uncle)
            {
                uncle.FreeNodeAtomically();
                grandParent.FreeNodeAtomically();
                node.Parent.FreeNodeAtomically();
                node.FreeNodeAtomically();
                return(false);
            }

            localArea[0] = node;
            localArea[1] = node.Parent;
            localArea[2] = grandParent;
            localArea[3] = uncle;

            if (!GetFlagsAndMarkersAbove(grandParent, localArea, pid, 0))
            {
                uncle.FreeNodeAtomically();
                grandParent.FreeNodeAtomically();
                node.Parent.FreeNodeAtomically();
                node.FreeNodeAtomically();
                return(false);
            }
            return(true);
        }
コード例 #20
0
        private bool Delete(TKey key, Guid pid)
        {
            RedBlackNode <TKey, TValue> y = null, z = null, x = null;
            var localArea = new RedBlackNode <TKey, TValue> [5];

            while (true)
            {
                // GetNode will return a locked node
                z = GetNodeForDelete(key);

                if (z == null)
                {
                    continue;
                }

                // Find key-order successor, locked y is returned
                y = FindSuccessor(z);
                if (y == null)
                {
                    //Console.WriteLine("No successor");
                    z.FreeNodeAtomically();
                    continue;
                }
                //we  now hold a flag on y and z

                if (!SetupLocalAreaForDelete(y, localArea, pid, z))
                {
                    y.FreeNodeAtomically();
                    if (y != z)
                    {
                        z.FreeNodeAtomically();
                    }
                    continue;
                }
                else
                {
                    break;
                }
            }

            x = y.Left.IsSentinel ? y.Right : y.Left;

            // unlink y from the tree
            x.Parent = y.Parent;
            if (y.Parent != null)
            {
                if (y == y.Parent.Left)
                {
                    y.Parent.Left = x;
                }
                else
                {
                    y.Parent.Right = x;
                }
            }
            else
            {
                _root = x;
            }

            // copy the values from y (the replacement node) to the node being deleted.
            // note: this effectively deletes the node.
            if (y != z)
            {
                z.Key  = y.Key;
                z.Data = y.Data;
                // Release z only when it is not in local area
                bool isZinLocalArea = false;
                foreach (var node in localArea)
                {
                    if (node == z)
                    {
                        isZinLocalArea = true;
                        break;
                    }
                }
                if (!isZinLocalArea)
                {
                    z.FreeNodeAtomically();
                }
                y.FreeNodeAtomically();
            }

            if (y.Color == RedBlackNodeType.Black)
            {
                BalanceTreeAfterDelete(x, localArea, pid);
            }
            else
            {
                // Release markers of local area
                var intentionMarkers = new RedBlackNode <TKey, TValue> [4];
                while (true)
                {
                    if (GetFlagsForMarkers(localArea[1], pid, intentionMarkers, z))
                    {
                        break;
                    }
                }
                foreach (var node in intentionMarkers)
                {
                    node.Marker = Guid.Empty;
                }
                ReleaseFlags(pid, false, intentionMarkers.ToList());

                // Release flags of local area
                foreach (var node in localArea)
                {
                    node?.FreeNodeAtomically();
                }
            }

            return(true);
        }
コード例 #21
0
        private void Insert(RedBlackNode <TKey, TValue> newNode, RedBlackNode <TKey, TValue>[] localArea, Guid pid)
        {
            while (true)
            {
                if (_root == null)
                {
                    if (!_dummy.OccupyNodeAtomically())
                    {
                        continue;
                    }
                    if (!_dummy.Left.IsSentinel)
                    {
                        _dummy.FreeNodeAtomically();
                        continue;
                    }
                    newNode.OccupyNodeAtomically();

                    // first node added
                    newNode.Parent = _dummy;
                    _dummy.Left    = newNode;
                    _root          = newNode;
                    break;
                }

                RedBlackNode <TKey, TValue> workNode = _root, nextNode = _root;
                if (!workNode.OccupyNodeAtomically())
                {
                    continue;
                }
                var isLocalAreaOccupied = false;

                while (true)
                {
                    newNode.Parent = workNode;
                    int result = newNode.Key.CompareTo(workNode.Key);
                    if (result == 0)
                    {
                        throw new Exception("duplicate key");
                    }

                    if (result > 0)
                    {
                        nextNode = workNode.Right;
                    }
                    else
                    {
                        nextNode = workNode.Left;
                    }

                    if (nextNode.IsSentinel)
                    {
                        isLocalAreaOccupied = OccupyLocalAreaForInsert(newNode, localArea, pid);
                        break;
                    }

                    if (!nextNode.OccupyNodeAtomically())
                    {
                        workNode.FreeNodeAtomically();
                        break;
                    }

                    if (nextNode.Parent != workNode)
                    {
                        workNode.FreeNodeAtomically();
                        nextNode.FreeNodeAtomically();
                        break;
                    }

                    workNode.FreeNodeAtomically();
                    workNode = nextNode;
                }

                if (isLocalAreaOccupied)
                {
                    break;
                }
            }

            // insert node into tree starting at parent's location
            if (newNode != _root)
            {
                if (newNode.Key.CompareTo(newNode.Parent.Key) > 0)
                {
                    newNode.Parent.Right = newNode;
                }
                else
                {
                    newNode.Parent.Left = newNode;
                }
            }
        }
コード例 #22
0
        private void MoveLocalAreaUpwardForInsert(RedBlackNode <TKey, TValue> node, RedBlackNode <TKey, TValue>[] working, Guid pid)
        {
            while (true)
            {
                if (GetFlagsAndMarkersAbove(node, working, pid, 2))
                {
                    break;
                }
            }

            RedBlackNode <TKey, TValue> newParent = node.Parent, newGrandParent = node.Parent.Parent, newUncle = null;

            while (true)
            {
                newUncle = newGrandParent.Left == node.Parent ? newGrandParent.Right : newGrandParent.Left;

                if (!IsIn(newUncle, pid))
                {
                    if (newUncle.OccupyNodeAtomically())
                    {
                        //check if uncle is not changed
                        var temp_uncle = newGrandParent.Left == node.Parent ? newGrandParent.Right : newGrandParent.Left;
                        if (newUncle != temp_uncle)
                        {
                            newUncle.FreeNodeAtomically();
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                else
                {
                    break;
                }
            }

            // release flag on old local area
            List <RedBlackNode <TKey, TValue> > nodesToRelease = new List <RedBlackNode <TKey, TValue> >();

            nodesToRelease.Add(working[0]);
            nodesToRelease.Add(working[1]);
            nodesToRelease.Add(working[3]);
            ReleaseFlags(pid, true, nodesToRelease);

            working[0] = node;
            working[1] = newParent;
            working[2] = newGrandParent;
            working[3] = newUncle;
        }