rbtree.c 14 KB

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