rbtree.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. * Copyright (c) 2010-2015 Richard Braun.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * Upstream site with license notes :
  18. * http://git.sceen.net/rbraun/librbraun.git/
  19. *
  20. *
  21. * Red-black tree.
  22. */
  23. #ifndef KERN_RBTREE_H
  24. #define KERN_RBTREE_H
  25. #include <assert.h>
  26. #include <stddef.h>
  27. #include <stdint.h>
  28. #include <kern/macros.h>
  29. // Indexes of the left and right nodes in the children array of a node.
  30. #define RBTREE_LEFT 0
  31. #define RBTREE_RIGHT 1
  32. // Insertion point identifier.
  33. typedef uintptr_t rbtree_slot_t;
  34. /*
  35. * Red-black node structure.
  36. *
  37. * To reduce the number of branches and the instruction cache footprint,
  38. * the left and right child pointers are stored in an array, and the symmetry
  39. * of most tree operations is exploited by using left/right variables when
  40. * referring to children.
  41. *
  42. * In addition, this implementation assumes that all nodes are 4-byte aligned,
  43. * so that the least significant bit of the parent member can be used to store
  44. * the color of the node. This is true for all modern 32 and 64 bits
  45. * architectures, as long as the nodes aren't embedded in structures with
  46. * special alignment constraints such as member packing.
  47. */
  48. struct rbtree_node
  49. {
  50. uintptr_t parent;
  51. struct rbtree_node *children[2];
  52. };
  53. // Red-black tree structure.
  54. struct rbtree
  55. {
  56. struct rbtree_node *root;
  57. };
  58. // Static tree initializer.
  59. #define RBTREE_INITIALIZER { NULL }
  60. /*
  61. * Masks applied on the parent member of a node to obtain either the
  62. * color or the parent address.
  63. */
  64. #define RBTREE_COLOR_MASK ((uintptr_t)0x1)
  65. #define RBTREE_PARENT_MASK (~(uintptr_t)0x3)
  66. // Node colors.
  67. #define RBTREE_COLOR_RED 0
  68. #define RBTREE_COLOR_BLACK 1
  69. /*
  70. * Masks applied on slots to obtain either the child index or the parent
  71. * address.
  72. */
  73. #define RBTREE_SLOT_INDEX_MASK 0x1UL
  74. #define RBTREE_SLOT_PARENT_MASK (~RBTREE_SLOT_INDEX_MASK)
  75. // Return true if the given index is a valid child index.
  76. static inline int
  77. rbtree_check_index (int index)
  78. {
  79. return (index == (index & 1));
  80. }
  81. /*
  82. * Convert the result of a comparison into an index in the children array
  83. * (0 or 1).
  84. *
  85. * This function is mostly used when looking up a node.
  86. */
  87. static inline int
  88. rbtree_d2i (int diff)
  89. {
  90. return (diff > 0);
  91. }
  92. // Return true if the given pointer is suitably aligned.
  93. static inline int
  94. rbtree_node_check_alignment (const struct rbtree_node *node)
  95. {
  96. return (((uintptr_t)node & ~RBTREE_PARENT_MASK) == 0);
  97. }
  98. // Return the parent of a node.
  99. static inline struct rbtree_node*
  100. rbtree_node_parent (const struct rbtree_node *node)
  101. {
  102. return ((struct rbtree_node *)(node->parent & RBTREE_PARENT_MASK));
  103. }
  104. // Translate an insertion point into a slot.
  105. static inline rbtree_slot_t
  106. rbtree_slot (struct rbtree_node *parent, int index)
  107. {
  108. assert (rbtree_node_check_alignment (parent));
  109. assert (rbtree_check_index (index));
  110. return ((rbtree_slot_t) parent | index);
  111. }
  112. // Extract the parent address from a slot.
  113. static inline struct rbtree_node*
  114. rbtree_slot_parent (rbtree_slot_t slot)
  115. {
  116. return ((struct rbtree_node *)(slot & RBTREE_SLOT_PARENT_MASK));
  117. }
  118. // Extract the index from a slot.
  119. static inline int
  120. rbtree_slot_index (rbtree_slot_t slot)
  121. {
  122. return (slot & RBTREE_SLOT_INDEX_MASK);
  123. }
  124. /*
  125. * Insert a node in a tree, rebalancing it if necessary.
  126. *
  127. * The index parameter is the index in the children array of the parent where
  128. * the new node is to be inserted. It is ignored if the parent is NULL.
  129. *
  130. * This function is intended to be used by the rbtree_insert() macro only.
  131. */
  132. void rbtree_insert_rebalance (struct rbtree *tree, struct rbtree_node *parent,
  133. int index, struct rbtree_node *node);
  134. /*
  135. * Return the previous or next node relative to a location in a tree.
  136. *
  137. * The parent and index parameters define the location, which can be empty.
  138. * The direction parameter is either RBTREE_LEFT (to obtain the previous
  139. * node) or RBTREE_RIGHT (to obtain the next one).
  140. */
  141. struct rbtree_node* rbtree_nearest (struct rbtree_node *parent, int index,
  142. int direction);
  143. /*
  144. * Return the first or last node of a tree.
  145. *
  146. * The direction parameter is either RBTREE_LEFT (to obtain the first node)
  147. * or RBTREE_RIGHT (to obtain the last one).
  148. */
  149. struct rbtree_node* rbtree_firstlast (const struct rbtree *tree, int direction);
  150. /*
  151. * Return the node next to, or previous to the given node.
  152. *
  153. * The direction parameter is either RBTREE_LEFT (to obtain the previous node)
  154. * or RBTREE_RIGHT (to obtain the next one).
  155. */
  156. struct rbtree_node* rbtree_walk (struct rbtree_node *node, int direction);
  157. /*
  158. * Return the left-most deepest node of a tree, which is the starting point of
  159. * the postorder traversal performed by rbtree_for_each_remove().
  160. */
  161. struct rbtree_node* rbtree_postwalk_deepest (const struct rbtree *tree);
  162. // Unlink a node from its tree and return the next (right) node in postorder.
  163. struct rbtree_node* rbtree_postwalk_unlink (struct rbtree_node *node);
  164. // Initialize a tree.
  165. static inline void
  166. rbtree_init (struct rbtree *tree)
  167. {
  168. tree->root = NULL;
  169. }
  170. /*
  171. * Initialize a node.
  172. *
  173. * A node is in no tree when its parent points to itself.
  174. */
  175. static inline void
  176. rbtree_node_init (struct rbtree_node *node)
  177. {
  178. assert (rbtree_node_check_alignment (node));
  179. node->parent = (uintptr_t)node | RBTREE_COLOR_RED;
  180. node->children[RBTREE_LEFT] = NULL;
  181. node->children[RBTREE_RIGHT] = NULL;
  182. }
  183. // Return true if node is in no tree.
  184. static inline int
  185. rbtree_node_unlinked (const struct rbtree_node *node)
  186. {
  187. return (rbtree_node_parent (node) == node);
  188. }
  189. /*
  190. * Macro that evaluates to the address of the structure containing the
  191. * given node based on the given type and member.
  192. */
  193. #define rbtree_entry(node, type, member) structof (node, type, member)
  194. // Return true if tree is empty.
  195. static inline int
  196. rbtree_empty (const struct rbtree *tree)
  197. {
  198. return (tree->root == NULL);
  199. }
  200. /*
  201. * Look up a node in a tree.
  202. *
  203. * Note that implementing the lookup algorithm as a macro gives two benefits:
  204. * First, it avoids the overhead of a callback function. Next, the type of the
  205. * cmp_fn parameter isn't rigid. The only guarantee offered by this
  206. * implementation is that the key parameter is the first parameter given to
  207. * cmp_fn. This way, users can pass only the value they need for comparison
  208. * instead of e.g. allocating a full structure on the stack.
  209. *
  210. * See rbtree_insert().
  211. */
  212. #define rbtree_lookup(tree, key, cmp_fn) \
  213. MACRO_BEGIN \
  214. \
  215. struct rbtree_node *cur_ = (tree)->root; \
  216. \
  217. while (cur_ != NULL) \
  218. { \
  219. int diff_ = cmp_fn (key, cur_); \
  220. if (! diff) \
  221. break; \
  222. \
  223. cur_ = cur_->children[rbtree_d2i (diff_)]; \
  224. } \
  225. \
  226. cur_; \
  227. MACRO_END
  228. /*
  229. * Look up a node or one of its nearest nodes in a tree.
  230. *
  231. * This macro essentially acts as rbtree_lookup() but if no entry matched
  232. * the key, an additional step is performed to obtain the next or previous
  233. * node, depending on the direction (left or right).
  234. *
  235. * The constraints that apply to the key parameter are the same as for
  236. * rbtree_lookup().
  237. */
  238. #define rbtree_lookup_nearest(tree, key, cmp_fn, dir) \
  239. MACRO_BEGIN \
  240. \
  241. struct rbtree_node *prev_ = NULL, *cur_ = (tree)->root; \
  242. int index_ = -1; \
  243. \
  244. while (cur_ != NULL) \
  245. { \
  246. int diff_ = cmp_fn (key, cur_); \
  247. if (! diff_) \
  248. break; \
  249. \
  250. prev_ = cur_; \
  251. index_ = rbtree_d2i (diff_); \
  252. cur_ = cur_->children[index_]; \
  253. } \
  254. \
  255. if (! cur_) \
  256. cur_ = rbtree_nearest (prev_, index_, dir); \
  257. \
  258. cur_; \
  259. MACRO_END
  260. /*
  261. * Insert a node in a tree.
  262. *
  263. * This macro performs a standard lookup to obtain the insertion point of
  264. * the given node in the tree (it is assumed that the inserted node never
  265. * compares equal to any other entry in the tree) and links the node. It
  266. * then checks red-black rules violations, and rebalances the tree if
  267. * necessary.
  268. *
  269. * Unlike rbtree_lookup(), the cmp_fn parameter must compare two complete
  270. * entries, so it is suggested to use two different comparison inline
  271. * functions, such as myobj_cmp_lookup() and myobj_cmp_insert(). There is no
  272. * guarantee about the order of the nodes given to the comparison function.
  273. *
  274. * See rbtree_lookup().
  275. */
  276. #define rbtree_insert(tree, node, cmp_fn) \
  277. MACRO_BEGIN \
  278. \
  279. struct rbtree_node *prev_ = NULL, *cur_ = (tree)->root; \
  280. int index_ = -1; \
  281. cur_ = (tree)->root; \
  282. \
  283. while (cur_ != NULL) \
  284. { \
  285. int diff_ = cmp_fn (node, cur_); \
  286. assert (diff_); \
  287. prev_ = cur_; \
  288. index_ = rbtree_d2i (diff_); \
  289. cur_ = cur_->children[index_]; \
  290. } \
  291. \
  292. rbtree_insert_rebalance (tree, prev_, index_, node); \
  293. MACRO_END
  294. /*
  295. * Look up a node/slot pair in a tree.
  296. *
  297. * This macro essentially acts as rbtree_lookup() but in addition to a node,
  298. * it also returns a slot, which identifies an insertion point in the tree.
  299. * If the returned node is NULL, the slot can be used by rbtree_insert_slot()
  300. * to insert without the overhead of an additional lookup.
  301. *
  302. * The constraints that apply to the key parameter are the same as for
  303. * rbtree_lookup().
  304. */
  305. #define rbtree_lookup_slot(tree, key, cmp_fn, slot) \
  306. MACRO_BEGIN \
  307. \
  308. struct rbtree_node *prev_ = NULL, *cur_ = (tree)->root; \
  309. int index_ = 0; \
  310. \
  311. while (cur_ != NULL) \
  312. { \
  313. int diff_ = cmp_fn (key, cur_); \
  314. if (! diff_) \
  315. break; \
  316. \
  317. prev_ = cur_; \
  318. index_ = rbtree_d2i (diff_); \
  319. cur_ = cur_->children[index_]; \
  320. } \
  321. \
  322. (slot) = rbtree_slot(prev_, index_); \
  323. cur_; \
  324. MACRO_END
  325. /*
  326. * Insert a node at an insertion point in a tree.
  327. *
  328. * This macro essentially acts as rbtree_insert() except that it doesn't
  329. * obtain the insertion point with a standard lookup. The insertion point
  330. * is obtained by calling rbtree_lookup_slot(). In addition, the new node
  331. * must not compare equal to an existing node in the tree (i.e. the slot
  332. * must denote a NULL node).
  333. */
  334. static inline void
  335. rbtree_insert_slot (struct rbtree *tree, rbtree_slot_t slot,
  336. struct rbtree_node *node)
  337. {
  338. struct rbtree_node *parent = rbtree_slot_parent (slot);
  339. int index = rbtree_slot_index (slot);
  340. rbtree_insert_rebalance (tree, parent, index, node);
  341. }
  342. /*
  343. * Replace a node at an insertion point in a tree.
  344. *
  345. * The given node must compare strictly equal to the previous node,
  346. * which is returned on completion.
  347. */
  348. void* rbtree_replace_slot (struct rbtree *tree, rbtree_slot_t slot,
  349. struct rbtree_node *node);
  350. /*
  351. * Remove a node from a tree.
  352. *
  353. * After completion, the node is stale.
  354. */
  355. void rbtree_remove (struct rbtree *tree, struct rbtree_node *node);
  356. // Return the first node of a tree.
  357. #define rbtree_first(tree) rbtree_firstlast (tree, RBTREE_LEFT)
  358. // Return the last node of a tree.
  359. #define rbtree_last(tree) rbtree_firstlast (tree, RBTREE_RIGHT)
  360. // Return the node previous to the given node.
  361. #define rbtree_prev(node) rbtree_walk (node, RBTREE_LEFT)
  362. // Return the node next to the given node.
  363. #define rbtree_next(node) rbtree_walk(node, RBTREE_RIGHT)
  364. /*
  365. * Forge a loop to process all nodes of a tree, removing them when visited.
  366. *
  367. * This macro can only be used to destroy a tree, so that the resources used
  368. * by the entries can be released by the user. It basically removes all nodes
  369. * without doing any color checking.
  370. *
  371. * After completion, all nodes and the tree root member are stale.
  372. */
  373. #define rbtree_for_each_remove(tree, node, tmp) \
  374. for (struct rbtree_node *node = rbtree_postwalk_deepest (tree), \
  375. *tmp = rbtree_postwalk_unlink (node); \
  376. node != NULL; \
  377. node = tmp, tmp = rbtree_postwalk_unlink (node))
  378. #endif