![]() |
|
|||
File indexing completed on 2025-05-11 08:24:13
0001 /* SPDX-License-Identifier: BSD-2-Clause */ 0002 0003 /** 0004 * @file 0005 * 0006 * @ingroup RTEMSScoreRBTree 0007 * 0008 * @brief This header file provides interfaces of the 0009 * @ref RTEMSScoreRBTree which are used by the implementation, the 0010 * @ref RTEMSImplApplConfig, and the API. 0011 */ 0012 0013 /* 0014 * Copyright (c) 2010 Gedare Bloom. 0015 * 0016 * Redistribution and use in source and binary forms, with or without 0017 * modification, are permitted provided that the following conditions 0018 * are met: 0019 * 1. Redistributions of source code must retain the above copyright 0020 * notice, this list of conditions and the following disclaimer. 0021 * 2. Redistributions in binary form must reproduce the above copyright 0022 * notice, this list of conditions and the following disclaimer in the 0023 * documentation and/or other materials provided with the distribution. 0024 * 0025 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 0026 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 0027 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 0028 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 0029 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 0030 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 0031 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 0032 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 0033 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 0034 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 0035 * POSSIBILITY OF SUCH DAMAGE. 0036 */ 0037 0038 #ifndef _RTEMS_SCORE_RBTREE_H 0039 #define _RTEMS_SCORE_RBTREE_H 0040 0041 #include <rtems/score/bsd-tree.h> 0042 #include <rtems/score/basedefs.h> 0043 #include <rtems/score/assert.h> 0044 0045 #ifdef __cplusplus 0046 extern "C" { 0047 #endif 0048 0049 /** 0050 * @defgroup RTEMSScoreRBTree Red-Black Tree Handler 0051 * 0052 * @ingroup RTEMSScore 0053 * 0054 * @brief This group contains the Red-Black Tree Handler implementation. 0055 * 0056 * The Red-Black Tree Handler is used to manage sets of entities. This handler 0057 * provides two data structures. The rbtree Node data structure is included 0058 * as the first part of every data structure that will be placed on 0059 * a RBTree. The second data structure is rbtree Control which is used 0060 * to manage a set of rbtree Nodes. 0061 * 0062 * @{ 0063 */ 0064 0065 struct RBTree_Control; 0066 0067 /** 0068 * @brief Red-black tree node. 0069 * 0070 * This is used to manage each node (element) which is placed on a red-black 0071 * tree. 0072 */ 0073 typedef struct RBTree_Node { 0074 RTEMS_RB_ENTRY(RBTree_Node) Node; 0075 } RBTree_Node; 0076 0077 /** 0078 * @brief Red-black tree control. 0079 * 0080 * This is used to manage a red-black tree. A red-black tree consists of a 0081 * tree of zero or more nodes. 0082 */ 0083 typedef RTEMS_RB_HEAD(RBTree_Control, RBTree_Node) RBTree_Control; 0084 0085 /** 0086 * @brief Initializer for an empty red-black tree with designator @a name. 0087 */ 0088 #define RBTREE_INITIALIZER_EMPTY( name ) \ 0089 RTEMS_RB_INITIALIZER( name ) 0090 0091 /** 0092 * @brief Definition for an empty red-black tree with designator @a name. 0093 */ 0094 #define RBTREE_DEFINE_EMPTY( name ) \ 0095 RBTree_Control name = RBTREE_INITIALIZER_EMPTY( name ) 0096 0097 /** 0098 * @brief Sets a red-black tree node as off-tree. 0099 * 0100 * Do not use this function on nodes which are a part of a tree. 0101 * 0102 * @param[out] the_node The node to set off-tree. 0103 * 0104 * @see _RBTree_Is_node_off_tree(). 0105 */ 0106 static inline void _RBTree_Set_off_tree( RBTree_Node *the_node ) 0107 { 0108 RTEMS_RB_COLOR( the_node, Node ) = -1; 0109 } 0110 0111 /** 0112 * @brief Checks if this red-black tree node is off-tree. 0113 * 0114 * @param the_node The node to test. 0115 * 0116 * @retval true The node is not a part of a tree (off-tree). 0117 * @retval false The node is part of a tree. 0118 * 0119 * @see _RBTree_Set_off_tree(). 0120 */ 0121 static inline bool _RBTree_Is_node_off_tree( 0122 const RBTree_Node *the_node 0123 ) 0124 { 0125 return RTEMS_RB_COLOR( the_node, Node ) == -1; 0126 } 0127 0128 /** 0129 * @brief Rebalances the red-black tree after insertion of the node. 0130 * 0131 * @param[in, out] the_rbtree The red-black tree control. 0132 * @param[in, out] the_node The most recently inserted node. 0133 */ 0134 void _RBTree_Insert_color( 0135 RBTree_Control *the_rbtree, 0136 RBTree_Node *the_node 0137 ); 0138 0139 /** 0140 * @brief Initializes a red-black tree node. 0141 * 0142 * In debug configurations, the node is set off tree. In all other 0143 * configurations, this function does nothing. 0144 * 0145 * @param[out] the_node The red-black tree node to initialize. 0146 */ 0147 static inline void _RBTree_Initialize_node( RBTree_Node *the_node ) 0148 { 0149 #if defined(RTEMS_DEBUG) 0150 _RBTree_Set_off_tree( the_node ); 0151 #else 0152 (void) the_node; 0153 #endif 0154 } 0155 0156 /** 0157 * @brief Adds a child node to a parent node. 0158 * 0159 * @param child The child node. 0160 * @param[out] parent The parent node. 0161 * @param[out] link The child node link of the parent node. 0162 */ 0163 static inline void _RBTree_Add_child( 0164 RBTree_Node *child, 0165 RBTree_Node *parent, 0166 RBTree_Node **link 0167 ) 0168 { 0169 _Assert( _RBTree_Is_node_off_tree( child ) ); 0170 RTEMS_RB_SET( child, parent, Node ); 0171 *link = child; 0172 } 0173 0174 /** 0175 * @brief Inserts the node into the red-black tree using the specified parent 0176 * node and link. 0177 * 0178 * @param[in, out] the_rbtree The red-black tree control. 0179 * @param[in, out] the_node The node to insert. 0180 * @param[out] parent The parent node. 0181 * @param[out] link The child node link of the parent node. 0182 * 0183 * @code 0184 * #include <rtems/score/rbtree.h> 0185 * 0186 * typedef struct { 0187 * int value; 0188 * RBTree_Node Node; 0189 * } Some_Node; 0190 * 0191 * bool _Some_Less( 0192 * const RBTree_Node *a, 0193 * const RBTree_Node *b 0194 * ) 0195 * { 0196 * const Some_Node *aa = RTEMS_CONTAINER_OF( a, Some_Node, Node ); 0197 * const Some_Node *bb = RTEMS_CONTAINER_OF( b, Some_Node, Node ); 0198 * 0199 * return aa->value < bb->value; 0200 * } 0201 * 0202 * void _Some_Insert( 0203 * RBTree_Control *the_rbtree, 0204 * Some_Node *the_node 0205 * ) 0206 * { 0207 * RBTree_Node **link = _RBTree_Root_reference( the_rbtree ); 0208 * RBTree_Node *parent = NULL; 0209 * 0210 * while ( *link != NULL ) { 0211 * parent = *link; 0212 * 0213 * if ( _Some_Less( &the_node->Node, parent ) ) { 0214 * link = _RBTree_Left_reference( parent ); 0215 * } else { 0216 * link = _RBTree_Right_reference( parent ); 0217 * } 0218 * } 0219 * 0220 * _RBTree_Insert_with_parent( the_rbtree, &the_node->Node, parent, link ); 0221 * } 0222 * @endcode 0223 */ 0224 static inline void _RBTree_Insert_with_parent( 0225 RBTree_Control *the_rbtree, 0226 RBTree_Node *the_node, 0227 RBTree_Node *parent, 0228 RBTree_Node **link 0229 ) 0230 { 0231 _RBTree_Add_child( the_node, parent, link ); 0232 _RBTree_Insert_color( the_rbtree, the_node ); 0233 } 0234 0235 /** 0236 * @brief Extracts (removes) the node from the red-black tree. 0237 * 0238 * This function does not set the node off-tree. In the case this is desired, then 0239 * call _RBTree_Set_off_tree() after the extraction. 0240 * 0241 * In the case the node to extract is not a node of the tree, then this function 0242 * yields unpredictable results. 0243 * 0244 * @param[in, out] the_rbtree The red-black tree control. 0245 * @param[out] the_node The node to extract. 0246 */ 0247 void _RBTree_Extract( 0248 RBTree_Control *the_rbtree, 0249 RBTree_Node *the_node 0250 ); 0251 0252 /** 0253 * @brief Returns a pointer to root node of the red-black tree. 0254 * 0255 * The root node may change after insert or extract operations. 0256 * 0257 * @param the_rbtree The red-black tree control. 0258 * 0259 * @retval root The root node. 0260 * @retval NULL The tree is empty. 0261 * 0262 * @see _RBTree_Is_root(). 0263 */ 0264 static inline RBTree_Node *_RBTree_Root( 0265 const RBTree_Control *the_rbtree 0266 ) 0267 { 0268 return RTEMS_RB_ROOT( the_rbtree ); 0269 } 0270 0271 /** 0272 * @brief Returns a reference to the root pointer of the red-black tree. 0273 * 0274 * @param the_rbtree The red-black tree control. 0275 * 0276 * @retval pointer Pointer to the root node. 0277 * @retval NULL The tree is empty. 0278 */ 0279 static inline RBTree_Node **_RBTree_Root_reference( 0280 RBTree_Control *the_rbtree 0281 ) 0282 { 0283 return &RTEMS_RB_ROOT( the_rbtree ); 0284 } 0285 0286 /** 0287 * @brief Returns a constant reference to the root pointer of the red-black tree. 0288 * 0289 * @param the_rbtree The red-black tree control. 0290 * 0291 * @retval pointer Pointer to the root node. 0292 * @retval NULL The tree is empty. 0293 */ 0294 static inline RBTree_Node * const *_RBTree_Root_const_reference( 0295 const RBTree_Control *the_rbtree 0296 ) 0297 { 0298 return &RTEMS_RB_ROOT( the_rbtree ); 0299 } 0300 0301 /** 0302 * @brief Returns a pointer to the parent of this node. 0303 * 0304 * The node must have a parent, thus it is invalid to use this function for the 0305 * root node or a node that is not part of a tree. To test for the root node 0306 * compare with _RBTree_Root() or use _RBTree_Is_root(). 0307 * 0308 * @param the_node The node of interest. 0309 * 0310 * @retval parent The parent of this node. 0311 * @retval undefined The node is the root node or not part of a tree. 0312 */ 0313 static inline RBTree_Node *_RBTree_Parent( 0314 const RBTree_Node *the_node 0315 ) 0316 { 0317 return RTEMS_RB_PARENT( the_node, Node ); 0318 } 0319 0320 /** 0321 * @brief Returns pointer to the left of this node. 0322 * 0323 * This function returns a pointer to the left node of this node. 0324 * 0325 * @param the_node is the node to be operated upon. 0326 * 0327 * @return This method returns the left node on the rbtree. 0328 */ 0329 static inline RBTree_Node *_RBTree_Left( 0330 const RBTree_Node *the_node 0331 ) 0332 { 0333 return RTEMS_RB_LEFT( the_node, Node ); 0334 } 0335 0336 /** 0337 * @brief Returns a reference to the left child pointer of the red-black tree 0338 * node. 0339 * 0340 * @param the_node is the node to be operated upon. 0341 * 0342 * @return This method returns a reference to the left child pointer on the rbtree. 0343 */ 0344 static inline RBTree_Node **_RBTree_Left_reference( 0345 RBTree_Node *the_node 0346 ) 0347 { 0348 return &RTEMS_RB_LEFT( the_node, Node ); 0349 } 0350 0351 /** 0352 * @brief Returns pointer to the right of this node. 0353 * 0354 * This function returns a pointer to the right node of this node. 0355 * 0356 * @param the_node is the node to be operated upon. 0357 * 0358 * @return This method returns the right node on the rbtree. 0359 */ 0360 static inline RBTree_Node *_RBTree_Right( 0361 const RBTree_Node *the_node 0362 ) 0363 { 0364 return RTEMS_RB_RIGHT( the_node, Node ); 0365 } 0366 0367 /** 0368 * @brief Returns a reference to the right child pointer of the red-black tree 0369 * node. 0370 * 0371 * @param the_node is the node to be operated upon. 0372 * 0373 * @return This method returns a reference to the right child pointer on the rbtree. 0374 */ 0375 static inline RBTree_Node **_RBTree_Right_reference( 0376 RBTree_Node *the_node 0377 ) 0378 { 0379 return &RTEMS_RB_RIGHT( the_node, Node ); 0380 } 0381 0382 /** 0383 * @brief Checks if the RBTree is empty. 0384 * 0385 * This function returns true if there are no nodes on @a the_rbtree and 0386 * false otherwise. 0387 * 0388 * @param the_rbtree is the rbtree to be operated upon. 0389 * 0390 * @retval true There are no nodes on @a the_rbtree. 0391 * @retval false There are nodes on @a the_rbtree. 0392 */ 0393 static inline bool _RBTree_Is_empty( 0394 const RBTree_Control *the_rbtree 0395 ) 0396 { 0397 return RTEMS_RB_EMPTY( the_rbtree ); 0398 } 0399 0400 /** 0401 * @brief Checks if this node is the root node of a red-black tree. 0402 * 0403 * The root node may change after insert or extract operations. In case the 0404 * node is not a node of a tree, then this function yields unpredictable 0405 * results. 0406 * 0407 * @param the_node The node of interest. 0408 * 0409 * @retval true @a the_node is the root node. 0410 * @retval false @a the_node is not the root node. 0411 * 0412 * @see _RBTree_Root(). 0413 */ 0414 static inline bool _RBTree_Is_root( 0415 const RBTree_Node *the_node 0416 ) 0417 { 0418 return _RBTree_Parent( the_node ) == NULL; 0419 } 0420 0421 /** 0422 * @brief Initializes this RBTree as empty. 0423 * 0424 * This routine initializes @a the_rbtree to contain zero nodes. 0425 * 0426 * @param[out] the_rbtree The rbtree to initialize. 0427 */ 0428 static inline void _RBTree_Initialize_empty( 0429 RBTree_Control *the_rbtree 0430 ) 0431 { 0432 RTEMS_RB_INIT( the_rbtree ); 0433 } 0434 0435 /** 0436 * @brief Initializes this red-black tree to contain exactly the specified 0437 * node. 0438 * 0439 * @param[out] the_rbtree The red-black tree control. 0440 * @param[out] the_node The one and only node. 0441 */ 0442 static inline void _RBTree_Initialize_one( 0443 RBTree_Control *the_rbtree, 0444 RBTree_Node *the_node 0445 ) 0446 { 0447 _Assert( _RBTree_Is_node_off_tree( the_node ) ); 0448 RTEMS_RB_ROOT( the_rbtree ) = the_node; 0449 RTEMS_RB_PARENT( the_node, Node ) = NULL; 0450 RTEMS_RB_LEFT( the_node, Node ) = NULL; 0451 RTEMS_RB_RIGHT( the_node, Node ) = NULL; 0452 RTEMS_RB_COLOR( the_node, Node ) = RTEMS_RB_BLACK; 0453 } 0454 0455 /** 0456 * @brief Returns the minimum node of the red-black tree. 0457 * 0458 * @param the_rbtree The red-black tree control. 0459 * 0460 * @retval node The minimum node. 0461 * @retval NULL The red-black tree is empty. 0462 */ 0463 RBTree_Node *_RBTree_Minimum( const RBTree_Control *the_rbtree ); 0464 0465 /** 0466 * @brief Returns the maximum node of the red-black tree. 0467 * 0468 * @param the_rbtree The red-black tree control. 0469 * 0470 * @retval node The maximum node. 0471 * @retval NULL The red-black tree is empty. 0472 */ 0473 RBTree_Node *_RBTree_Maximum( const RBTree_Control *the_rbtree ); 0474 0475 /** 0476 * @brief Returns the predecessor of a node. 0477 * 0478 * @param node is the node. 0479 * 0480 * @retval node The predecessor node. 0481 * @retval NULL The predecessor does not exist. 0482 */ 0483 RBTree_Node *_RBTree_Predecessor( const RBTree_Node *node ); 0484 0485 /** 0486 * @brief Returns the successor of a node. 0487 * 0488 * @param node is the node. 0489 * 0490 * @retval node The successor node. 0491 * @retval NULL The successor does not exist. 0492 */ 0493 RBTree_Node *_RBTree_Successor( const RBTree_Node *node ); 0494 0495 /** 0496 * @brief Replaces a node in the red-black tree without a rebalance. 0497 * 0498 * @param[in, out] the_rbtree The red-black tree control. 0499 * @param victim The victim node. 0500 * @param[out] replacement The replacement node. 0501 */ 0502 void _RBTree_Replace_node( 0503 RBTree_Control *the_rbtree, 0504 RBTree_Node *victim, 0505 RBTree_Node *replacement 0506 ); 0507 0508 /** 0509 * @brief Inserts the node into the red-black tree. 0510 * 0511 * @param[in, out] the_rbtree The red-black tree control. 0512 * @param[out] the_node The node to insert. 0513 * @param key The key of the node to insert. This key must be equal to the key 0514 * stored in the node to insert. The separate key parameter is provided for 0515 * two reasons. Firstly, it allows to share the less operator with 0516 * _RBTree_Find_inline(). Secondly, the compiler may generate better code if 0517 * the key is stored in a local variable. 0518 * @param less Must return true if the specified key is less than the key of 0519 * the node, otherwise false. 0520 * 0521 * @retval true The inserted node is the new minimum node according to the 0522 * specified less order function. 0523 * @retval false The inserted node is not the new minimum node according to the 0524 * specified less order function. 0525 */ 0526 static inline bool _RBTree_Insert_inline( 0527 RBTree_Control *the_rbtree, 0528 RBTree_Node *the_node, 0529 const void *key, 0530 bool ( *less )( const void *, const RBTree_Node * ) 0531 ) 0532 { 0533 RBTree_Node **link; 0534 RBTree_Node *parent; 0535 bool is_new_minimum; 0536 0537 link = _RBTree_Root_reference( the_rbtree ); 0538 parent = NULL; 0539 is_new_minimum = true; 0540 0541 while ( *link != NULL ) { 0542 parent = *link; 0543 0544 if ( ( *less )( key, parent ) ) { 0545 link = _RBTree_Left_reference( parent ); 0546 } else { 0547 link = _RBTree_Right_reference( parent ); 0548 is_new_minimum = false; 0549 } 0550 } 0551 0552 _RBTree_Add_child( the_node, parent, link ); 0553 _RBTree_Insert_color( the_rbtree, the_node ); 0554 return is_new_minimum; 0555 } 0556 0557 /** 0558 * @brief Finds an object in the red-black tree with the specified key. 0559 * 0560 * @param the_rbtree The red-black tree control. 0561 * @param key The key to look after. 0562 * @param equal Must return true if the specified key equals the key of the 0563 * node, otherwise false. 0564 * @param less Must return true if the specified key is less than the key of 0565 * the node, otherwise false. 0566 * @param map In case a node with the specified key is found, then this 0567 * function is called to map the node to the object returned. Usually it 0568 * performs some offset operation via RTEMS_CONTAINER_OF() to map the node to 0569 * its containing object. Thus, the return type is a void pointer and not a 0570 * red-black tree node. 0571 * 0572 * @retval object An object with the specified key. 0573 * @retval NULL No object with the specified key exists in the red-black tree. 0574 */ 0575 static inline void *_RBTree_Find_inline( 0576 const RBTree_Control *the_rbtree, 0577 const void *key, 0578 bool ( *equal )( const void *, const RBTree_Node * ), 0579 bool ( *less )( const void *, const RBTree_Node * ), 0580 void *( *map )( RBTree_Node * ) 0581 ) 0582 { 0583 RBTree_Node * const *link; 0584 RBTree_Node *parent; 0585 0586 link = _RBTree_Root_const_reference( the_rbtree ); 0587 parent = NULL; 0588 0589 while ( *link != NULL ) { 0590 parent = *link; 0591 0592 if ( ( *equal )( key, parent ) ) { 0593 return ( *map )( parent ); 0594 } else if ( ( *less )( key, parent ) ) { 0595 link = _RBTree_Left_reference( parent ); 0596 } else { 0597 link = _RBTree_Right_reference( parent ); 0598 } 0599 } 0600 0601 return NULL; 0602 } 0603 0604 /** 0605 * @brief Returns the container of the first node of the specified red-black 0606 * tree in postorder. 0607 * 0608 * Postorder traversal may be used to delete all nodes of a red-black tree. 0609 * 0610 * @param the_rbtree The red-black tree control. 0611 * @param offset The offset to the red-black tree node in the container structure. 0612 * 0613 * @retval container The container of the first node of the specified red-black 0614 * tree in postorder. 0615 * @retval NULL The red-black tree is empty. 0616 * 0617 * @see _RBTree_Postorder_next(). 0618 * 0619 * @code 0620 * #include <rtems/score/rbtree.h> 0621 * 0622 * typedef struct { 0623 * int data; 0624 * RBTree_Node Node; 0625 * } Container_Control; 0626 * 0627 * void visit( Container_Control *the_container ); 0628 * 0629 * void postorder_traversal( RBTree_Control *the_rbtree ) 0630 * { 0631 * Container_Control *the_container; 0632 * 0633 * the_container = _RBTree_Postorder_first( 0634 * the_rbtree, 0635 * offsetof( Container_Control, Node ) 0636 * ); 0637 * 0638 * while ( the_container != NULL ) { 0639 * visit( the_container ); 0640 * 0641 * the_container = _RBTree_Postorder_next( 0642 * &the_container->Node, 0643 * offsetof( Container_Control, Node ) 0644 * ); 0645 * } 0646 * } 0647 * @endcode 0648 */ 0649 void *_RBTree_Postorder_first( 0650 const RBTree_Control *the_rbtree, 0651 size_t offset 0652 ); 0653 0654 /** 0655 * @brief Returns the container of the next node in postorder. 0656 * 0657 * @param the_node The red-black tree node. The node must not be NULL. 0658 * @param offset The offset to the red-black tree node in the container structure. 0659 * 0660 * @retval container The container of the next node in postorder. 0661 * @retval NULL The node is NULL or there is no next node in postorder. 0662 * 0663 * @see _RBTree_Postorder_first(). 0664 */ 0665 void *_RBTree_Postorder_next( 0666 const RBTree_Node *the_node, 0667 size_t offset 0668 ); 0669 0670 /** @} */ 0671 0672 #ifdef __cplusplus 0673 } 0674 #endif 0675 0676 #endif 0677 /* end of include file */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |