source: rtems/cpukit/score/src/rbtreeextract.c @ 62181b21

4.115
Last change on this file since 62181b21 was 9b4422a2, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 15:09:24

Remove All CVS Id Strings Possible Using a Script

Script does what is expected and tries to do it as
smartly as possible.

+ remove occurrences of two blank comment lines

next to each other after Id string line removed.

+ remove entire comment blocks which only exited to

contain CVS Ids

+ If the processing left a blank line at the top of

a file, it was removed.

  • Property mode set to 100644
File size: 7.7 KB
Line 
1/*
2 *  Copyright (c) 2010 Gedare Bloom.
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.com/license/LICENSE.
7 */
8
9#if HAVE_CONFIG_H
10#include "config.h"
11#endif
12
13#include <rtems/system.h>
14#include <rtems/score/address.h>
15#include <rtems/score/rbtree.h>
16#include <rtems/score/isr.h>
17
18/** @brief  Validate and fix-up tree properties after deleting a node
19 *
20 *  This routine is called on a black node, @a the_node, after its deletion.
21 *  This function maintains the properties of the red-black tree.
22 *
23 *  @note It does NOT disable interrupts to ensure the atomicity
24 *        of the extract operation.
25 */
26static void _RBTree_Extract_validate_unprotected(
27    RBTree_Node *the_node
28    )
29{
30  RBTree_Node *parent, *sibling;
31  RBTree_Direction dir;
32
33  parent = the_node->parent;
34  if(!parent->parent) return;
35
36  sibling = _RBTree_Sibling(the_node);
37
38  /* continue to correct tree as long as the_node is black and not the root */
39  while (!_RBTree_Is_red(the_node) && parent->parent) {
40
41    /* if sibling is red, switch parent (black) and sibling colors,
42     * then rotate parent left, making the sibling be the_node's grandparent.
43     * Now the_node has a black sibling and red parent. After rotation,
44     * update sibling pointer.
45     */
46    if (_RBTree_Is_red(sibling)) {
47      parent->color = RBT_RED;
48      sibling->color = RBT_BLACK;
49      dir = the_node != parent->child[0];
50      _RBTree_Rotate(parent, dir);
51      sibling = parent->child[_RBTree_Opposite_direction(dir)];
52    }
53
54    /* sibling is black, see if both of its children are also black. */
55    if (!_RBTree_Is_red(sibling->child[RBT_RIGHT]) &&
56        !_RBTree_Is_red(sibling->child[RBT_LEFT])) {
57        sibling->color = RBT_RED;
58        if (_RBTree_Is_red(parent)) {
59          parent->color = RBT_BLACK;
60          break;
61        }
62        the_node = parent; /* done if parent is red */
63        parent = the_node->parent;
64        sibling = _RBTree_Sibling(the_node);
65    } else {
66      /* at least one of sibling's children is red. we now proceed in two
67       * cases, either the_node is to the left or the right of the parent.
68       * In both cases, first check if one of sibling's children is black,
69       * and if so rotate in the proper direction and update sibling pointer.
70       * Then switch the sibling and parent colors, and rotate through parent.
71       */
72      dir = the_node != parent->child[0];
73      if (!_RBTree_Is_red(sibling->child[_RBTree_Opposite_direction(dir)])) {
74        sibling->color = RBT_RED;
75        sibling->child[dir]->color = RBT_BLACK;
76        _RBTree_Rotate(sibling, _RBTree_Opposite_direction(dir));
77        sibling = parent->child[_RBTree_Opposite_direction(dir)];
78      }
79      sibling->color = parent->color;
80      parent->color = RBT_BLACK;
81      sibling->child[_RBTree_Opposite_direction(dir)]->color = RBT_BLACK;
82      _RBTree_Rotate(parent, dir);
83      break; /* done */
84    }
85  } /* while */
86  if(!the_node->parent->parent) the_node->color = RBT_BLACK;
87}
88
89/** @brief Extract a Node (unprotected)
90 *
91 *  This routine extracts (removes) @a the_node from @a the_rbtree.
92 *
93 *  @note It does NOT disable interrupts to ensure the atomicity
94 *        of the extract operation.
95 */
96void _RBTree_Extract_unprotected(
97    RBTree_Control *the_rbtree,
98    RBTree_Node *the_node
99    )
100{
101  RBTree_Node *leaf, *target;
102  RBTree_Color victim_color;
103  RBTree_Direction dir;
104
105  if (!the_node) return;
106
107  /* check if min needs to be updated */
108  if (the_node == the_rbtree->first[RBT_LEFT]) {
109    RBTree_Node *next;
110    next = _RBTree_Successor_unprotected(the_node);
111    the_rbtree->first[RBT_LEFT] = next;
112  }
113
114  /* Check if max needs to be updated. min=max for 1 element trees so
115   * do not use else if here. */
116  if (the_node == the_rbtree->first[RBT_RIGHT]) {
117    RBTree_Node *previous;
118    previous = _RBTree_Predecessor_unprotected(the_node);
119    the_rbtree->first[RBT_RIGHT] = previous;
120  }
121
122  /* if the_node has at most one non-null child then it is safe to proceed
123   * check if both children are non-null, if so then we must find a target node
124   * either max in node->child[RBT_LEFT] or min in node->child[RBT_RIGHT],
125   * and replace the_node with the target node. This maintains the binary
126   * search tree property, but may violate the red-black properties.
127   */
128
129  if (the_node->child[RBT_LEFT] && the_node->child[RBT_RIGHT]) {
130    target = the_node->child[RBT_LEFT]; /* find max in node->child[RBT_LEFT] */
131    while (target->child[RBT_RIGHT]) target = target->child[RBT_RIGHT];
132
133    /* if the target node has a child, need to move it up the tree into
134     * target's position (target is the right child of target->parent)
135     * when target vacates it. if there is no child, then target->parent
136     * should become NULL. This may cause the coloring to be violated.
137     * For now we store the color of the node being deleted in victim_color.
138     */
139    leaf = target->child[RBT_LEFT];
140    if(leaf) {
141      leaf->parent = target->parent;
142    } else {
143      /* fix the tree here if the child is a null leaf. */
144      _RBTree_Extract_validate_unprotected(target);
145    }
146    victim_color = target->color;
147    dir = target != target->parent->child[0];
148    target->parent->child[dir] = leaf;
149
150    /* now replace the_node with target */
151    dir = the_node != the_node->parent->child[0];
152    the_node->parent->child[dir] = target;
153
154    /* set target's new children to the original node's children */
155    target->child[RBT_RIGHT] = the_node->child[RBT_RIGHT];
156    if (the_node->child[RBT_RIGHT])
157      the_node->child[RBT_RIGHT]->parent = target;
158    target->child[RBT_LEFT] = the_node->child[RBT_LEFT];
159    if (the_node->child[RBT_LEFT])
160      the_node->child[RBT_LEFT]->parent = target;
161
162    /* finally, update the parent node and recolor. target has completely
163     * replaced the_node, and target's child has moved up the tree if needed.
164     * the_node is no longer part of the tree, although it has valid pointers
165     * still.
166     */
167    target->parent = the_node->parent;
168    target->color = the_node->color;
169  } else {
170    /* the_node has at most 1 non-null child. Move the child in to
171     * the_node's location in the tree. This may cause the coloring to be
172     * violated. We will fix it later.
173     * For now we store the color of the node being deleted in victim_color.
174     */
175    leaf = the_node->child[RBT_LEFT] ?
176              the_node->child[RBT_LEFT] : the_node->child[RBT_RIGHT];
177    if( leaf ) {
178      leaf->parent = the_node->parent;
179    } else {
180      /* fix the tree here if the child is a null leaf. */
181      _RBTree_Extract_validate_unprotected(the_node);
182    }
183    victim_color = the_node->color;
184
185    /* remove the_node from the tree */
186    dir = the_node != the_node->parent->child[0];
187    the_node->parent->child[dir] = leaf;
188  }
189
190  /* fix coloring. leaf has moved up the tree. The color of the deleted
191   * node is in victim_color. There are two cases:
192   *   1. Deleted a red node, its child must be black. Nothing must be done.
193   *   2. Deleted a black node, its child must be red. Paint child black.
194   */
195  if (victim_color == RBT_BLACK) { /* eliminate case 1 */
196    if (leaf) {
197      leaf->color = RBT_BLACK; /* case 2 */
198    }
199  }
200
201  /* Wipe the_node */
202  _RBTree_Set_off_rbtree(the_node);
203
204  /* set root to black, if it exists */
205  if (the_rbtree->root) the_rbtree->root->color = RBT_BLACK;
206}
207
208
209/*
210 *  _RBTree_Extract
211 *
212 *  This kernel routine deletes the given node from a rbtree.
213 *
214 *  Input parameters:
215 *    node - pointer to node in rbtree to be deleted
216 *
217 *  Output parameters:  NONE
218 *
219 *  INTERRUPT LATENCY:
220 *    only case
221 */
222
223void _RBTree_Extract(
224  RBTree_Control *the_rbtree,
225  RBTree_Node *the_node
226)
227{
228  ISR_Level level;
229
230  _ISR_Disable( level );
231    _RBTree_Extract_unprotected( the_rbtree, the_node );
232  _ISR_Enable( level );
233}
Note: See TracBrowser for help on using the repository browser.