rbtree.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  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, int direction)
  105. {
  106. struct starpu_rbtree_node *parent, *rnode;
  107. int left, right;
  108. left = direction;
  109. right = 1 - left;
  110. parent = starpu_rbtree_parent(node);
  111. rnode = node->children[right];
  112. node->children[right] = rnode->children[left];
  113. if (rnode->children[left] != NULL)
  114. starpu_rbtree_set_parent(rnode->children[left], node);
  115. rnode->children[left] = node;
  116. starpu_rbtree_set_parent(rnode, parent);
  117. if (unlikely(parent == NULL))
  118. tree->root = rnode;
  119. else
  120. parent->children[starpu_rbtree_index(node, parent)] = rnode;
  121. starpu_rbtree_set_parent(node, rnode);
  122. }
  123. void starpu_rbtree_insert_rebalance(struct starpu_rbtree *tree, struct starpu_rbtree_node *parent,
  124. int index, struct starpu_rbtree_node *node)
  125. {
  126. struct starpu_rbtree_node *grand_parent, *uncle, *tmp;
  127. int left, right;
  128. assert(starpu_rbtree_check_alignment(parent));
  129. assert(starpu_rbtree_check_alignment(node));
  130. node->parent = (unsigned long)parent | STARPU_RBTREE_COLOR_RED;
  131. node->children[STARPU_RBTREE_LEFT] = NULL;
  132. node->children[STARPU_RBTREE_RIGHT] = NULL;
  133. if (unlikely(parent == NULL))
  134. tree->root = node;
  135. else
  136. parent->children[index] = node;
  137. for (;;)
  138. {
  139. if (parent == NULL)
  140. {
  141. starpu_rbtree_set_black(node);
  142. break;
  143. }
  144. if (starpu_rbtree_is_black(parent))
  145. break;
  146. grand_parent = starpu_rbtree_parent(parent);
  147. assert(grand_parent != NULL);
  148. left = starpu_rbtree_index(parent, grand_parent);
  149. right = 1 - left;
  150. uncle = grand_parent->children[right];
  151. /*
  152. * Uncle is red. Flip colors and repeat at grand parent.
  153. */
  154. if ((uncle != NULL) && starpu_rbtree_is_red(uncle))
  155. {
  156. starpu_rbtree_set_black(uncle);
  157. starpu_rbtree_set_black(parent);
  158. starpu_rbtree_set_red(grand_parent);
  159. node = grand_parent;
  160. parent = starpu_rbtree_parent(node);
  161. continue;
  162. }
  163. /*
  164. * Node is the right child of its parent. Rotate left at parent.
  165. */
  166. if (parent->children[right] == node)
  167. {
  168. starpu_rbtree_rotate(tree, parent, left);
  169. tmp = node;
  170. node = parent;
  171. parent = tmp;
  172. }
  173. /*
  174. * Node is the left child of its parent. Handle colors, rotate right
  175. * at grand parent, and leave.
  176. */
  177. starpu_rbtree_set_black(parent);
  178. starpu_rbtree_set_red(grand_parent);
  179. starpu_rbtree_rotate(tree, grand_parent, right);
  180. break;
  181. }
  182. assert(starpu_rbtree_is_black(tree->root));
  183. }
  184. void starpu_rbtree_remove(struct starpu_rbtree *tree, struct starpu_rbtree_node *node)
  185. {
  186. struct starpu_rbtree_node *child, *parent, *brother;
  187. int color, left, right;
  188. if (node->children[STARPU_RBTREE_LEFT] == NULL)
  189. child = node->children[STARPU_RBTREE_RIGHT];
  190. else if (node->children[STARPU_RBTREE_RIGHT] == NULL)
  191. child = node->children[STARPU_RBTREE_LEFT];
  192. else
  193. {
  194. struct starpu_rbtree_node *successor;
  195. /*
  196. * Two-children case: replace the node with its successor.
  197. */
  198. successor = node->children[STARPU_RBTREE_RIGHT];
  199. while (successor->children[STARPU_RBTREE_LEFT] != NULL)
  200. successor = successor->children[STARPU_RBTREE_LEFT];
  201. color = starpu_rbtree_color(successor);
  202. child = successor->children[STARPU_RBTREE_RIGHT];
  203. parent = starpu_rbtree_parent(node);
  204. if (unlikely(parent == NULL))
  205. tree->root = successor;
  206. else
  207. parent->children[starpu_rbtree_index(node, parent)] = successor;
  208. parent = starpu_rbtree_parent(successor);
  209. /*
  210. * Set parent directly to keep the original color.
  211. */
  212. successor->parent = node->parent;
  213. successor->children[STARPU_RBTREE_LEFT] = node->children[STARPU_RBTREE_LEFT];
  214. starpu_rbtree_set_parent(successor->children[STARPU_RBTREE_LEFT], successor);
  215. if (node == parent)
  216. parent = successor;
  217. else
  218. {
  219. successor->children[STARPU_RBTREE_RIGHT] = node->children[STARPU_RBTREE_RIGHT];
  220. starpu_rbtree_set_parent(successor->children[STARPU_RBTREE_RIGHT], successor);
  221. parent->children[STARPU_RBTREE_LEFT] = child;
  222. if (child != NULL)
  223. starpu_rbtree_set_parent(child, parent);
  224. }
  225. goto update_color;
  226. }
  227. /*
  228. * Node has at most one child.
  229. */
  230. color = starpu_rbtree_color(node);
  231. parent = starpu_rbtree_parent(node);
  232. if (child != NULL)
  233. starpu_rbtree_set_parent(child, parent);
  234. if (unlikely(parent == NULL))
  235. tree->root = child;
  236. else
  237. parent->children[starpu_rbtree_index(node, parent)] = child;
  238. /*
  239. * The node has been removed, update the colors. The child pointer can
  240. * be null, in which case it is considered a black leaf.
  241. */
  242. update_color:
  243. if (color == STARPU_RBTREE_COLOR_RED)
  244. return;
  245. for (;;)
  246. {
  247. if ((child != NULL) && starpu_rbtree_is_red(child))
  248. {
  249. starpu_rbtree_set_black(child);
  250. break;
  251. }
  252. if (parent == NULL)
  253. break;
  254. left = starpu_rbtree_index(child, parent);
  255. right = 1 - left;
  256. brother = parent->children[right];
  257. /*
  258. * Brother is red. Recolor and rotate left at parent so that brother
  259. * becomes black.
  260. */
  261. if (starpu_rbtree_is_red(brother))
  262. {
  263. starpu_rbtree_set_black(brother);
  264. starpu_rbtree_set_red(parent);
  265. starpu_rbtree_rotate(tree, parent, left);
  266. brother = parent->children[right];
  267. }
  268. /*
  269. * Brother has no red child. Recolor and repeat at parent.
  270. */
  271. if (((brother->children[STARPU_RBTREE_LEFT] == NULL)
  272. || starpu_rbtree_is_black(brother->children[STARPU_RBTREE_LEFT]))
  273. && ((brother->children[STARPU_RBTREE_RIGHT] == NULL)
  274. || starpu_rbtree_is_black(brother->children[STARPU_RBTREE_RIGHT])))
  275. {
  276. starpu_rbtree_set_red(brother);
  277. child = parent;
  278. parent = starpu_rbtree_parent(child);
  279. continue;
  280. }
  281. /*
  282. * Brother's right child is black. Recolor and rotate right at brother.
  283. */
  284. if ((brother->children[right] == NULL)
  285. || starpu_rbtree_is_black(brother->children[right]))
  286. {
  287. starpu_rbtree_set_black(brother->children[left]);
  288. starpu_rbtree_set_red(brother);
  289. starpu_rbtree_rotate(tree, brother, right);
  290. brother = parent->children[right];
  291. }
  292. /*
  293. * Brother's left child is black. Exchange parent and brother colors
  294. * (we already know brother is black), set brother's right child black,
  295. * rotate left at parent and leave.
  296. */
  297. starpu_rbtree_set_color(brother, starpu_rbtree_color(parent));
  298. starpu_rbtree_set_black(parent);
  299. starpu_rbtree_set_black(brother->children[right]);
  300. starpu_rbtree_rotate(tree, parent, left);
  301. break;
  302. }
  303. assert((tree->root == NULL) || starpu_rbtree_is_black(tree->root));
  304. }
  305. struct starpu_rbtree_node * starpu_rbtree_nearest(struct starpu_rbtree_node *parent, int index,
  306. int direction)
  307. {
  308. assert(starpu_rbtree_check_index(direction));
  309. if (parent == NULL)
  310. return NULL;
  311. assert(starpu_rbtree_check_index(index));
  312. if (index != direction)
  313. return parent;
  314. return starpu_rbtree_walk(parent, direction);
  315. }
  316. struct starpu_rbtree_node * starpu_rbtree_firstlast(const struct starpu_rbtree *tree, int direction)
  317. {
  318. struct starpu_rbtree_node *prev, *cur;
  319. assert(starpu_rbtree_check_index(direction));
  320. prev = NULL;
  321. for (cur = tree->root; cur != NULL; cur = cur->children[direction])
  322. prev = cur;
  323. return prev;
  324. }
  325. struct starpu_rbtree_node * starpu_rbtree_walk(struct starpu_rbtree_node *node, int direction)
  326. {
  327. int left, right;
  328. assert(starpu_rbtree_check_index(direction));
  329. left = direction;
  330. right = 1 - left;
  331. if (node == NULL)
  332. return NULL;
  333. if (node->children[left] != NULL)
  334. {
  335. node = node->children[left];
  336. while (node->children[right] != NULL)
  337. node = node->children[right];
  338. }
  339. else
  340. {
  341. struct starpu_rbtree_node *parent;
  342. int index;
  343. for (;;)
  344. {
  345. parent = starpu_rbtree_parent(node);
  346. if (parent == NULL)
  347. return NULL;
  348. index = starpu_rbtree_index(node, parent);
  349. node = parent;
  350. if (index == right)
  351. break;
  352. }
  353. }
  354. return node;
  355. }
  356. /*
  357. * Return the left-most deepest child node of the given node.
  358. */
  359. static struct starpu_rbtree_node * starpu_rbtree_find_deepest(struct starpu_rbtree_node *node)
  360. {
  361. struct starpu_rbtree_node *parent;
  362. assert(node != NULL);
  363. for (;;)
  364. {
  365. parent = node;
  366. node = node->children[STARPU_RBTREE_LEFT];
  367. if (node == NULL)
  368. {
  369. node = parent->children[STARPU_RBTREE_RIGHT];
  370. if (node == NULL)
  371. return parent;
  372. }
  373. }
  374. }
  375. struct starpu_rbtree_node * starpu_rbtree_postwalk_deepest(const struct starpu_rbtree *tree)
  376. {
  377. struct starpu_rbtree_node *node;
  378. node = tree->root;
  379. if (node == NULL)
  380. return NULL;
  381. return starpu_rbtree_find_deepest(node);
  382. }
  383. struct starpu_rbtree_node * starpu_rbtree_postwalk_unlink(struct starpu_rbtree_node *node)
  384. {
  385. struct starpu_rbtree_node *parent;
  386. int index;
  387. if (node == NULL)
  388. return NULL;
  389. assert(node->children[STARPU_RBTREE_LEFT] == NULL);
  390. assert(node->children[STARPU_RBTREE_RIGHT] == NULL);
  391. parent = starpu_rbtree_parent(node);
  392. if (parent == NULL)
  393. return NULL;
  394. index = starpu_rbtree_index(node, parent);
  395. parent->children[index] = NULL;
  396. node = parent->children[STARPU_RBTREE_RIGHT];
  397. if (node == NULL)
  398. return parent;
  399. return starpu_rbtree_find_deepest(node);
  400. }