rbtree.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /*
  2. * Copyright (c) 2010, 2012 Richard Braun.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include <common/rbtree.h>
  26. #include <common/rbtree_i.h>
  27. #include <sys/types.h>
  28. #define unlikely(expr) __builtin_expect(!!(expr), 0)
  29. /*
  30. * Return the index of a node in the children array of its parent.
  31. *
  32. * The parent parameter must not be null, and must be the parent of the
  33. * given node.
  34. */
  35. static inline int starpu_rbtree_index(const struct starpu_rbtree_node *node,
  36. const struct starpu_rbtree_node *parent)
  37. {
  38. assert(parent != NULL);
  39. assert((node == NULL) || (starpu_rbtree_parent(node) == parent));
  40. if (parent->children[STARPU_RBTREE_LEFT] == node)
  41. return STARPU_RBTREE_LEFT;
  42. assert(parent->children[STARPU_RBTREE_RIGHT] == node);
  43. return STARPU_RBTREE_RIGHT;
  44. }
  45. /*
  46. * Return the color of a node.
  47. */
  48. static inline int starpu_rbtree_color(const struct starpu_rbtree_node *node)
  49. {
  50. return node->parent & STARPU_RBTREE_COLOR_MASK;
  51. }
  52. /*
  53. * Return true if the node is red.
  54. */
  55. static inline int starpu_rbtree_is_red(const struct starpu_rbtree_node *node)
  56. {
  57. return starpu_rbtree_color(node) == STARPU_RBTREE_COLOR_RED;
  58. }
  59. /*
  60. * Return true if the node is black.
  61. */
  62. static inline int starpu_rbtree_is_black(const struct starpu_rbtree_node *node)
  63. {
  64. return starpu_rbtree_color(node) == STARPU_RBTREE_COLOR_BLACK;
  65. }
  66. /*
  67. * Set the parent of a node, retaining its current color.
  68. */
  69. static inline void starpu_rbtree_set_parent(struct starpu_rbtree_node *node,
  70. struct starpu_rbtree_node *parent)
  71. {
  72. assert(starpu_rbtree_check_alignment(node));
  73. assert(starpu_rbtree_check_alignment(parent));
  74. node->parent = (unsigned long)parent | (node->parent & STARPU_RBTREE_COLOR_MASK);
  75. }
  76. /*
  77. * Set the color of a node, retaining its current parent.
  78. */
  79. static inline void starpu_rbtree_set_color(struct starpu_rbtree_node *node, int color)
  80. {
  81. assert((color & ~STARPU_RBTREE_COLOR_MASK) == 0);
  82. node->parent = (node->parent & STARPU_RBTREE_PARENT_MASK) | color;
  83. }
  84. /*
  85. * Set the color of a node to red, retaining its current parent.
  86. */
  87. static inline void starpu_rbtree_set_red(struct starpu_rbtree_node *node)
  88. {
  89. starpu_rbtree_set_color(node, STARPU_RBTREE_COLOR_RED);
  90. }
  91. /*
  92. * Set the color of a node to black, retaining its current parent.
  93. */
  94. static inline void starpu_rbtree_set_black(struct starpu_rbtree_node *node)
  95. {
  96. starpu_rbtree_set_color(node, STARPU_RBTREE_COLOR_BLACK);
  97. }
  98. /*
  99. * Perform a tree rotation, rooted at the given node.
  100. *
  101. * The direction parameter defines the rotation direction and is either
  102. * STARPU_RBTREE_LEFT or STARPU_RBTREE_RIGHT.
  103. */
  104. static void starpu_rbtree_rotate(struct starpu_rbtree *tree, struct starpu_rbtree_node *node,
  105. int direction)
  106. {
  107. struct starpu_rbtree_node *parent, *rnode;
  108. int left, right;
  109. left = direction;
  110. right = 1 - left;
  111. parent = starpu_rbtree_parent(node);
  112. rnode = node->children[right];
  113. node->children[right] = rnode->children[left];
  114. if (rnode->children[left] != NULL)
  115. starpu_rbtree_set_parent(rnode->children[left], node);
  116. rnode->children[left] = node;
  117. starpu_rbtree_set_parent(rnode, parent);
  118. if (unlikely(parent == NULL))
  119. tree->root = rnode;
  120. else
  121. parent->children[starpu_rbtree_index(node, parent)] = rnode;
  122. starpu_rbtree_set_parent(node, rnode);
  123. }
  124. void starpu_rbtree_insert_rebalance(struct starpu_rbtree *tree, struct starpu_rbtree_node *parent,
  125. int index, struct starpu_rbtree_node *node)
  126. {
  127. struct starpu_rbtree_node *grand_parent, *uncle, *tmp;
  128. int left, right;
  129. assert(starpu_rbtree_check_alignment(parent));
  130. assert(starpu_rbtree_check_alignment(node));
  131. node->parent = (unsigned long)parent | STARPU_RBTREE_COLOR_RED;
  132. node->children[STARPU_RBTREE_LEFT] = NULL;
  133. node->children[STARPU_RBTREE_RIGHT] = NULL;
  134. if (unlikely(parent == NULL))
  135. tree->root = node;
  136. else
  137. parent->children[index] = node;
  138. for (;;) {
  139. if (parent == NULL) {
  140. starpu_rbtree_set_black(node);
  141. break;
  142. }
  143. if (starpu_rbtree_is_black(parent))
  144. break;
  145. grand_parent = starpu_rbtree_parent(parent);
  146. assert(grand_parent != NULL);
  147. left = starpu_rbtree_index(parent, grand_parent);
  148. right = 1 - left;
  149. uncle = grand_parent->children[right];
  150. /*
  151. * Uncle is red. Flip colors and repeat at grand parent.
  152. */
  153. if ((uncle != NULL) && starpu_rbtree_is_red(uncle)) {
  154. starpu_rbtree_set_black(uncle);
  155. starpu_rbtree_set_black(parent);
  156. starpu_rbtree_set_red(grand_parent);
  157. node = grand_parent;
  158. parent = starpu_rbtree_parent(node);
  159. continue;
  160. }
  161. /*
  162. * Node is the right child of its parent. Rotate left at parent.
  163. */
  164. if (parent->children[right] == node) {
  165. starpu_rbtree_rotate(tree, parent, left);
  166. tmp = node;
  167. node = parent;
  168. parent = tmp;
  169. }
  170. /*
  171. * Node is the left child of its parent. Handle colors, rotate right
  172. * at grand parent, and leave.
  173. */
  174. starpu_rbtree_set_black(parent);
  175. starpu_rbtree_set_red(grand_parent);
  176. starpu_rbtree_rotate(tree, grand_parent, right);
  177. break;
  178. }
  179. assert(starpu_rbtree_is_black(tree->root));
  180. }
  181. void starpu_rbtree_remove(struct starpu_rbtree *tree, struct starpu_rbtree_node *node)
  182. {
  183. struct starpu_rbtree_node *child, *parent, *brother;
  184. int color, left, right;
  185. if (node->children[STARPU_RBTREE_LEFT] == NULL)
  186. child = node->children[STARPU_RBTREE_RIGHT];
  187. else if (node->children[STARPU_RBTREE_RIGHT] == NULL)
  188. child = node->children[STARPU_RBTREE_LEFT];
  189. else {
  190. struct starpu_rbtree_node *successor;
  191. /*
  192. * Two-children case: replace the node with its successor.
  193. */
  194. successor = node->children[STARPU_RBTREE_RIGHT];
  195. while (successor->children[STARPU_RBTREE_LEFT] != NULL)
  196. successor = successor->children[STARPU_RBTREE_LEFT];
  197. color = starpu_rbtree_color(successor);
  198. child = successor->children[STARPU_RBTREE_RIGHT];
  199. parent = starpu_rbtree_parent(node);
  200. if (unlikely(parent == NULL))
  201. tree->root = successor;
  202. else
  203. parent->children[starpu_rbtree_index(node, parent)] = successor;
  204. parent = starpu_rbtree_parent(successor);
  205. /*
  206. * Set parent directly to keep the original color.
  207. */
  208. successor->parent = node->parent;
  209. successor->children[STARPU_RBTREE_LEFT] = node->children[STARPU_RBTREE_LEFT];
  210. starpu_rbtree_set_parent(successor->children[STARPU_RBTREE_LEFT], successor);
  211. if (node == parent)
  212. parent = successor;
  213. else {
  214. successor->children[STARPU_RBTREE_RIGHT] = node->children[STARPU_RBTREE_RIGHT];
  215. starpu_rbtree_set_parent(successor->children[STARPU_RBTREE_RIGHT], successor);
  216. parent->children[STARPU_RBTREE_LEFT] = child;
  217. if (child != NULL)
  218. starpu_rbtree_set_parent(child, parent);
  219. }
  220. goto update_color;
  221. }
  222. /*
  223. * Node has at most one child.
  224. */
  225. color = starpu_rbtree_color(node);
  226. parent = starpu_rbtree_parent(node);
  227. if (child != NULL)
  228. starpu_rbtree_set_parent(child, parent);
  229. if (unlikely(parent == NULL))
  230. tree->root = child;
  231. else
  232. parent->children[starpu_rbtree_index(node, parent)] = child;
  233. /*
  234. * The node has been removed, update the colors. The child pointer can
  235. * be null, in which case it is considered a black leaf.
  236. */
  237. update_color:
  238. if (color == STARPU_RBTREE_COLOR_RED)
  239. return;
  240. for (;;) {
  241. if ((child != NULL) && starpu_rbtree_is_red(child)) {
  242. starpu_rbtree_set_black(child);
  243. break;
  244. }
  245. if (parent == NULL)
  246. break;
  247. left = starpu_rbtree_index(child, parent);
  248. right = 1 - left;
  249. brother = parent->children[right];
  250. /*
  251. * Brother is red. Recolor and rotate left at parent so that brother
  252. * becomes black.
  253. */
  254. if (starpu_rbtree_is_red(brother)) {
  255. starpu_rbtree_set_black(brother);
  256. starpu_rbtree_set_red(parent);
  257. starpu_rbtree_rotate(tree, parent, left);
  258. brother = parent->children[right];
  259. }
  260. /*
  261. * Brother has no red child. Recolor and repeat at parent.
  262. */
  263. if (((brother->children[STARPU_RBTREE_LEFT] == NULL)
  264. || starpu_rbtree_is_black(brother->children[STARPU_RBTREE_LEFT]))
  265. && ((brother->children[STARPU_RBTREE_RIGHT] == NULL)
  266. || starpu_rbtree_is_black(brother->children[STARPU_RBTREE_RIGHT]))) {
  267. starpu_rbtree_set_red(brother);
  268. child = parent;
  269. parent = starpu_rbtree_parent(child);
  270. continue;
  271. }
  272. /*
  273. * Brother's right child is black. Recolor and rotate right at brother.
  274. */
  275. if ((brother->children[right] == NULL)
  276. || starpu_rbtree_is_black(brother->children[right])) {
  277. starpu_rbtree_set_black(brother->children[left]);
  278. starpu_rbtree_set_red(brother);
  279. starpu_rbtree_rotate(tree, brother, right);
  280. brother = parent->children[right];
  281. }
  282. /*
  283. * Brother's left child is black. Exchange parent and brother colors
  284. * (we already know brother is black), set brother's right child black,
  285. * rotate left at parent and leave.
  286. */
  287. starpu_rbtree_set_color(brother, starpu_rbtree_color(parent));
  288. starpu_rbtree_set_black(parent);
  289. starpu_rbtree_set_black(brother->children[right]);
  290. starpu_rbtree_rotate(tree, parent, left);
  291. break;
  292. }
  293. assert((tree->root == NULL) || starpu_rbtree_is_black(tree->root));
  294. }
  295. struct starpu_rbtree_node * starpu_rbtree_nearest(struct starpu_rbtree_node *parent, int index,
  296. int direction)
  297. {
  298. assert(starpu_rbtree_check_index(direction));
  299. if (parent == NULL)
  300. return NULL;
  301. assert(starpu_rbtree_check_index(index));
  302. if (index != direction)
  303. return parent;
  304. return starpu_rbtree_walk(parent, direction);
  305. }
  306. struct starpu_rbtree_node * starpu_rbtree_firstlast(const struct starpu_rbtree *tree, int direction)
  307. {
  308. struct starpu_rbtree_node *prev, *cur;
  309. assert(starpu_rbtree_check_index(direction));
  310. prev = NULL;
  311. for (cur = tree->root; cur != NULL; cur = cur->children[direction])
  312. prev = cur;
  313. return prev;
  314. }
  315. struct starpu_rbtree_node * starpu_rbtree_walk(struct starpu_rbtree_node *node, int direction)
  316. {
  317. int left, right;
  318. assert(starpu_rbtree_check_index(direction));
  319. left = direction;
  320. right = 1 - left;
  321. if (node == NULL)
  322. return NULL;
  323. if (node->children[left] != NULL) {
  324. node = node->children[left];
  325. while (node->children[right] != NULL)
  326. node = node->children[right];
  327. } else {
  328. struct starpu_rbtree_node *parent;
  329. int index;
  330. for (;;) {
  331. parent = starpu_rbtree_parent(node);
  332. if (parent == NULL)
  333. return NULL;
  334. index = starpu_rbtree_index(node, parent);
  335. node = parent;
  336. if (index == right)
  337. break;
  338. }
  339. }
  340. return node;
  341. }
  342. /*
  343. * Return the left-most deepest child node of the given node.
  344. */
  345. static struct starpu_rbtree_node * starpu_rbtree_find_deepest(struct starpu_rbtree_node *node)
  346. {
  347. struct starpu_rbtree_node *parent;
  348. assert(node != NULL);
  349. for (;;) {
  350. parent = node;
  351. node = node->children[STARPU_RBTREE_LEFT];
  352. if (node == NULL) {
  353. node = parent->children[STARPU_RBTREE_RIGHT];
  354. if (node == NULL)
  355. return parent;
  356. }
  357. }
  358. }
  359. struct starpu_rbtree_node * starpu_rbtree_postwalk_deepest(const struct starpu_rbtree *tree)
  360. {
  361. struct starpu_rbtree_node *node;
  362. node = tree->root;
  363. if (node == NULL)
  364. return NULL;
  365. return starpu_rbtree_find_deepest(node);
  366. }
  367. struct starpu_rbtree_node * starpu_rbtree_postwalk_unlink(struct starpu_rbtree_node *node)
  368. {
  369. struct starpu_rbtree_node *parent;
  370. int index;
  371. if (node == NULL)
  372. return NULL;
  373. assert(node->children[STARPU_RBTREE_LEFT] == NULL);
  374. assert(node->children[STARPU_RBTREE_RIGHT] == NULL);
  375. parent = starpu_rbtree_parent(node);
  376. if (parent == NULL)
  377. return NULL;
  378. index = starpu_rbtree_index(node, parent);
  379. parent->children[index] = NULL;
  380. node = parent->children[STARPU_RBTREE_RIGHT];
  381. if (node == NULL)
  382. return parent;
  383. return starpu_rbtree_find_deepest(node);
  384. }