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