예제 #1
0
        private RedBlackNode <TKey, TValue> GetNodeForDelete(TKey key)
        {
            // begin at root
            RedBlackNode <TKey, TValue> treeNode = _root;

            // Hold a flag on root
            if (!treeNode.OccupyNodeAtomically())
            {
                return(null);
            }
            // check if _root is locked
            if (treeNode != _root)
            {
                treeNode.FreeNodeAtomically();
                return(null);
            }
            var previousNode = treeNode;

            // 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;
                // Hold a flag on new treenode
                if (!treeNode.OccupyNodeAtomically())
                {
                    previousNode.FreeNodeAtomically();
                    return(null);
                }
                // check if correct node is locked
                if (treeNode != (result < 0 ? previousNode.Left : previousNode.Right))
                {
                    previousNode.FreeNodeAtomically();
                    treeNode.FreeNodeAtomically();
                    return(null);
                }
                previousNode.FreeNodeAtomically();
                previousNode = treeNode;
            }

            treeNode.FreeNodeAtomically();
            return(null);
        }
예제 #2
0
        private bool GetFlagForMarker(
            RedBlackNode <TKey, TValue> node,
            RedBlackNode <TKey, TValue> prevNode,
            List <RedBlackNode <TKey, TValue> > nodesToRelease,
            Guid pid,
            RedBlackNode <TKey, TValue> z = null)
        {
            if (z == null || z != node)
            {
                if (!IsIn(node, pid) && !node.OccupyNodeAtomically())
                {
                    ReleaseFlags(pid, false, nodesToRelease);
                    return(false);
                }

                nodesToRelease.Add(node);

                // verify parent is unchanged
                if (node != prevNode.Parent)
                {
                    ReleaseFlags(pid, false, nodesToRelease);
                    return(false);
                }
            }
            return(true);
        }
예제 #3
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;
        }
예제 #4
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;
            }
        }
예제 #5
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);
        }
예제 #6
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);
        }
예제 #7
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);
        }
예제 #8
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);
        }
예제 #9
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;
                }
            }
        }