Back to home page

LXR

 
 

    


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 */