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