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(); } }
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); }
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; }
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); }
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); }
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); }
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); }
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; } } }