Ejemplo n.º 1
0
        private void New(TKey key, TValue data, Guid pid)
        {
            if (data == null)
            {
                throw new Exception();
            }

            // traverse tree - find where node belongs

            // create new node
            var newNode = new RedBlackNode <TKey, TValue>(key, data);

            var localArea = new RedBlackNode <TKey, TValue> [4];

            Insert(newNode, localArea, pid);

            if (_root.Left.IsSentinel && _root.Right.IsSentinel)
            {
                _root.Color = RedBlackNodeType.Black;
                _dummy.FreeNodeAtomically();
                _dummy.Left.FreeNodeAtomically();
                return;
            }

            // restore red-black properties
            BalanceTreeAfterInsert(newNode, localArea, pid);

            // Release markers of local area
            var intentionMarkers = new RedBlackNode <TKey, TValue> [4];

            RedBlackNode <TKey, TValue> top = localArea[2];

            while (true)
            {
                if (GetFlagsForMarkers(top, pid, intentionMarkers, localArea[0]))
                {
                    break;
                }
            }
            foreach (var node in intentionMarkers)
            {
                if (node.Marker != pid)
                {
                    Console.WriteLine($"{node.Marker}, {pid}, {Thread.CurrentThread.Name}");
                }
                node.Marker = Guid.Empty;
            }
            ReleaseFlags(pid, false, intentionMarkers.ToList());

            foreach (var node in localArea)
            {
                node?.FreeNodeAtomically();
            }
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 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;
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 6
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);
        }
Ejemplo n.º 7
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);
        }
Ejemplo n.º 8
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;
                }
            }
        }