source: rtems/cpukit/include/rtems/score/rbtree.h @ a660e9dc

Last change on this file since a660e9dc was a660e9dc, checked in by Sebastian Huber <sebastian.huber@…>, on 09/08/22 at 08:37:05

Do not use RTEMS_INLINE_ROUTINE

Directly use "static inline" which is available in C99 and later. This brings
the RTEMS implementation closer to standard C.

Close #3935.

  • Property mode set to 100644
File size: 17.7 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSScoreRBTree
7 *
8 * @brief This header file provides interfaces of the
9 *   @ref RTEMSScoreRBTree which are used by the implementation, the
10 *   @ref RTEMSImplApplConfig, and the API.
11 */
12
13/*
14 *  Copyright (c) 2010 Gedare Bloom.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifndef _RTEMS_SCORE_RBTREE_H
39#define _RTEMS_SCORE_RBTREE_H
40
41#include <sys/tree.h>
42#include <rtems/score/basedefs.h>
43#include <rtems/score/assert.h>
44
45#ifdef __cplusplus
46extern "C" {
47#endif
48
49/**
50 * @defgroup RTEMSScoreRBTree Red-Black Tree Handler
51 *
52 * @ingroup RTEMSScore
53 *
54 * @brief This group contains the Red-Black Tree Handler implementation.
55 *
56 * The Red-Black Tree Handler is used to manage sets of entities.  This handler
57 * provides two data structures.  The rbtree Node data structure is included
58 * as the first part of every data structure that will be placed on
59 * a RBTree.  The second data structure is rbtree Control which is used
60 * to manage a set of rbtree Nodes.
61 *
62 * @{
63 */
64
65struct RBTree_Control;
66
67/**
68 * @brief Red-black tree node.
69 *
70 * This is used to manage each node (element) which is placed on a red-black
71 * tree.
72 */
73typedef struct RBTree_Node {
74  RB_ENTRY(RBTree_Node) Node;
75} RBTree_Node;
76
77/**
78 * @brief Red-black tree control.
79 *
80 * This is used to manage a red-black tree.  A red-black tree consists of a
81 * tree of zero or more nodes.
82 */
83typedef RB_HEAD(RBTree_Control, RBTree_Node) RBTree_Control;
84
85/**
86 * @brief Initializer for an empty red-black tree with designator @a name.
87 */
88#define RBTREE_INITIALIZER_EMPTY( name ) \
89  RB_INITIALIZER( name )
90
91/**
92 * @brief Definition for an empty red-black tree with designator @a name.
93 */
94#define RBTREE_DEFINE_EMPTY( name ) \
95  RBTree_Control name = RBTREE_INITIALIZER_EMPTY( name )
96
97/**
98 * @brief Sets a red-black tree node as off-tree.
99 *
100 * Do not use this function on nodes which are a part of a tree.
101 *
102 * @param[out] the_node The node to set off-tree.
103 *
104 * @see _RBTree_Is_node_off_tree().
105 */
106static inline void _RBTree_Set_off_tree( RBTree_Node *the_node )
107{
108  RB_COLOR( the_node, Node ) = -1;
109}
110
111/**
112 * @brief Checks if this red-black tree node is off-tree.
113 *
114 * @param the_node The node to test.
115 *
116 * @retval true The node is not a part of a tree (off-tree).
117 * @retval false The node is part of a tree.
118 *
119 * @see _RBTree_Set_off_tree().
120 */
121static inline bool _RBTree_Is_node_off_tree(
122  const RBTree_Node *the_node
123)
124{
125  return RB_COLOR( the_node, Node ) == -1;
126}
127
128/**
129 * @brief Rebalances the red-black tree after insertion of the node.
130 *
131 * @param[in, out] the_rbtree The red-black tree control.
132 * @param[in, out] the_node The most recently inserted node.
133 */
134void _RBTree_Insert_color(
135  RBTree_Control *the_rbtree,
136  RBTree_Node    *the_node
137);
138
139/**
140 * @brief Initializes a red-black tree node.
141 *
142 * In debug configurations, the node is set off tree.  In all other
143 * configurations, this function does nothing.
144 *
145 * @param[out] the_node The red-black tree node to initialize.
146 */
147static inline void _RBTree_Initialize_node( RBTree_Node *the_node )
148{
149#if defined(RTEMS_DEBUG)
150  _RBTree_Set_off_tree( the_node );
151#else
152  (void) the_node;
153#endif
154}
155
156/**
157 * @brief Adds a child node to a parent node.
158 *
159 * @param child The child node.
160 * @param[out] parent The parent node.
161 * @param[out] link The child node link of the parent node.
162 */
163static inline void _RBTree_Add_child(
164  RBTree_Node  *child,
165  RBTree_Node  *parent,
166  RBTree_Node **link
167)
168{
169  _Assert( _RBTree_Is_node_off_tree( child ) );
170  RB_SET( child, parent, Node );
171  *link = child;
172}
173
174/**
175 * @brief Inserts the node into the red-black tree using the specified parent
176 * node and link.
177 *
178 * @param[in, out] the_rbtree The red-black tree control.
179 * @param[in, out] the_node The node to insert.
180 * @param[out] parent The parent node.
181 * @param[out] link The child node link of the parent node.
182 *
183 * @code
184 * #include <rtems/score/rbtree.h>
185 *
186 * typedef struct {
187 *   int value;
188 *   RBTree_Node Node;
189 * } Some_Node;
190 *
191 * bool _Some_Less(
192 *   const RBTree_Node *a,
193 *   const RBTree_Node *b
194 * )
195 * {
196 *   const Some_Node *aa = RTEMS_CONTAINER_OF( a, Some_Node, Node );
197 *   const Some_Node *bb = RTEMS_CONTAINER_OF( b, Some_Node, Node );
198 *
199 *   return aa->value < bb->value;
200 * }
201 *
202 * void _Some_Insert(
203 *   RBTree_Control *the_rbtree,
204 *   Some_Node      *the_node
205 * )
206 * {
207 *   RBTree_Node **link = _RBTree_Root_reference( the_rbtree );
208 *   RBTree_Node  *parent = NULL;
209 *
210 *   while ( *link != NULL ) {
211 *     parent = *link;
212 *
213 *     if ( _Some_Less( &the_node->Node, parent ) ) {
214 *       link = _RBTree_Left_reference( parent );
215 *     } else {
216 *       link = _RBTree_Right_reference( parent );
217 *     }
218 *   }
219 *
220 *   _RBTree_Insert_with_parent( the_rbtree, &the_node->Node, parent, link );
221 * }
222 * @endcode
223 */
224static inline void _RBTree_Insert_with_parent(
225  RBTree_Control  *the_rbtree,
226  RBTree_Node     *the_node,
227  RBTree_Node     *parent,
228  RBTree_Node    **link
229)
230{
231  _RBTree_Add_child( the_node, parent, link );
232  _RBTree_Insert_color( the_rbtree, the_node );
233}
234
235/**
236 * @brief Extracts (removes) the node from the red-black tree.
237 *
238 * This function does not set the node off-tree.  In the case this is desired, then
239 * call _RBTree_Set_off_tree() after the extraction.
240 *
241 * In the case the node to extract is not a node of the tree, then this function
242 * yields unpredictable results.
243 *
244 * @param[in, out] the_rbtree The red-black tree control.
245 * @param[out] the_node The node to extract.
246 */
247void _RBTree_Extract(
248  RBTree_Control *the_rbtree,
249  RBTree_Node *the_node
250);
251
252/**
253 * @brief Returns a pointer to root node of the red-black tree.
254 *
255 * The root node may change after insert or extract operations.
256 *
257 * @param the_rbtree The red-black tree control.
258 *
259 * @retval root The root node.
260 * @retval NULL The tree is empty.
261 *
262 * @see _RBTree_Is_root().
263 */
264static inline RBTree_Node *_RBTree_Root(
265  const RBTree_Control *the_rbtree
266)
267{
268  return RB_ROOT( the_rbtree );
269}
270
271/**
272 * @brief Returns a reference to the root pointer of the red-black tree.
273 *
274 * @param the_rbtree The red-black tree control.
275 *
276 * @retval pointer Pointer to the root node.
277 * @retval NULL The tree is empty.
278 */
279static inline RBTree_Node **_RBTree_Root_reference(
280  RBTree_Control *the_rbtree
281)
282{
283  return &RB_ROOT( the_rbtree );
284}
285
286/**
287 * @brief Returns a constant reference to the root pointer of the red-black tree.
288 *
289 * @param the_rbtree The red-black tree control.
290 *
291 * @retval pointer Pointer to the root node.
292 * @retval NULL The tree is empty.
293 */
294static inline RBTree_Node * const *_RBTree_Root_const_reference(
295  const RBTree_Control *the_rbtree
296)
297{
298  return &RB_ROOT( the_rbtree );
299}
300
301/**
302 * @brief Returns a pointer to the parent of this node.
303 *
304 * The node must have a parent, thus it is invalid to use this function for the
305 * root node or a node that is not part of a tree.  To test for the root node
306 * compare with _RBTree_Root() or use _RBTree_Is_root().
307 *
308 * @param the_node The node of interest.
309 *
310 * @retval parent The parent of this node.
311 * @retval undefined The node is the root node or not part of a tree.
312 */
313static inline RBTree_Node *_RBTree_Parent(
314  const RBTree_Node *the_node
315)
316{
317  return RB_PARENT( the_node, Node );
318}
319
320/**
321 * @brief Returns pointer to the left of this node.
322 *
323 * This function returns a pointer to the left node of this node.
324 *
325 * @param the_node is the node to be operated upon.
326 *
327 * @return This method returns the left node on the rbtree.
328 */
329static inline RBTree_Node *_RBTree_Left(
330  const RBTree_Node *the_node
331)
332{
333  return RB_LEFT( the_node, Node );
334}
335
336/**
337 * @brief Returns a reference to the left child pointer of the red-black tree
338 * node.
339 *
340 * @param the_node is the node to be operated upon.
341 *
342 * @return This method returns a reference to the left child pointer on the rbtree.
343 */
344static inline RBTree_Node **_RBTree_Left_reference(
345  RBTree_Node *the_node
346)
347{
348  return &RB_LEFT( the_node, Node );
349}
350
351/**
352 * @brief Returns pointer to the right of this node.
353 *
354 * This function returns a pointer to the right node of this node.
355 *
356 * @param the_node is the node to be operated upon.
357 *
358 * @return This method returns the right node on the rbtree.
359 */
360static inline RBTree_Node *_RBTree_Right(
361  const RBTree_Node *the_node
362)
363{
364  return RB_RIGHT( the_node, Node );
365}
366
367/**
368 * @brief Returns a reference to the right child pointer of the red-black tree
369 * node.
370 *
371 * @param the_node is the node to be operated upon.
372 *
373 * @return This method returns a reference to the right child pointer on the rbtree.
374 */
375static inline RBTree_Node **_RBTree_Right_reference(
376  RBTree_Node *the_node
377)
378{
379  return &RB_RIGHT( the_node, Node );
380}
381
382/**
383 * @brief Checks if the RBTree is empty.
384 *
385 * This function returns true if there are no nodes on @a the_rbtree and
386 * false otherwise.
387 *
388 * @param the_rbtree is the rbtree to be operated upon.
389 *
390 * @retval true There are no nodes on @a the_rbtree.
391 * @retval false There are nodes on @a the_rbtree.
392 */
393static inline bool _RBTree_Is_empty(
394  const RBTree_Control *the_rbtree
395)
396{
397  return RB_EMPTY( the_rbtree );
398}
399
400/**
401 * @brief Checks if this node is the root node of a red-black tree.
402 *
403 * The root node may change after insert or extract operations.  In case the
404 * node is not a node of a tree, then this function yields unpredictable
405 * results.
406 *
407 * @param the_node The node of interest.
408 *
409 * @retval true @a the_node is the root node.
410 * @retval false @a the_node is not the root node.
411 *
412 * @see _RBTree_Root().
413 */
414static inline bool _RBTree_Is_root(
415  const RBTree_Node *the_node
416)
417{
418  return _RBTree_Parent( the_node ) == NULL;
419}
420
421/**
422 * @brief Initializes this RBTree as empty.
423 *
424 * This routine initializes @a the_rbtree to contain zero nodes.
425 *
426 * @param[out] the_rbtree The rbtree to initialize.
427 */
428static inline void _RBTree_Initialize_empty(
429  RBTree_Control *the_rbtree
430)
431{
432  RB_INIT( the_rbtree );
433}
434
435/**
436 * @brief Initializes this red-black tree to contain exactly the specified
437 * node.
438 *
439 * @param[out] the_rbtree The red-black tree control.
440 * @param[out] the_node The one and only node.
441 */
442static inline void _RBTree_Initialize_one(
443  RBTree_Control *the_rbtree,
444  RBTree_Node    *the_node
445)
446{
447  _Assert( _RBTree_Is_node_off_tree( the_node ) );
448  RB_ROOT( the_rbtree ) = the_node;
449  RB_PARENT( the_node, Node ) = NULL;
450  RB_LEFT( the_node, Node ) = NULL;
451  RB_RIGHT( the_node, Node ) = NULL;
452  RB_COLOR( the_node, Node ) = RB_BLACK;
453}
454
455/**
456 * @brief Returns the minimum node of the red-black tree.
457 *
458 * @param the_rbtree The red-black tree control.
459 *
460 * @retval node The minimum node.
461 * @retval NULL The red-black tree is empty.
462 */
463RBTree_Node *_RBTree_Minimum( const RBTree_Control *the_rbtree );
464
465/**
466 * @brief Returns the maximum node of the red-black tree.
467 *
468 * @param the_rbtree The red-black tree control.
469 *
470 * @retval node The maximum node.
471 * @retval NULL The red-black tree is empty.
472 */
473RBTree_Node *_RBTree_Maximum( const RBTree_Control *the_rbtree );
474
475/**
476 * @brief Returns the predecessor of a node.
477 *
478 * @param node is the node.
479 *
480 * @retval node The predecessor node.
481 * @retval NULL The predecessor does not exist.
482 */
483RBTree_Node *_RBTree_Predecessor( const RBTree_Node *node );
484
485/**
486 * @brief Returns the successor of a node.
487 *
488 * @param node is the node.
489 *
490 * @retval node The successor node.
491 * @retval NULL The successor does not exist.
492 */
493RBTree_Node *_RBTree_Successor( const RBTree_Node *node );
494
495/**
496 * @brief Replaces a node in the red-black tree without a rebalance.
497 *
498 * @param[in, out] the_rbtree The red-black tree control.
499 * @param victim The victim node.
500 * @param[out] replacement The replacement node.
501 */
502void _RBTree_Replace_node(
503  RBTree_Control *the_rbtree,
504  RBTree_Node    *victim,
505  RBTree_Node    *replacement
506);
507
508/**
509 * @brief Inserts the node into the red-black tree.
510 *
511 * @param[in, out] the_rbtree The red-black tree control.
512 * @param[out] the_node The node to insert.
513 * @param key The key of the node to insert.  This key must be equal to the key
514 *   stored in the node to insert.  The separate key parameter is provided for
515 *   two reasons.  Firstly, it allows to share the less operator with
516 *   _RBTree_Find_inline().  Secondly, the compiler may generate better code if
517 *   the key is stored in a local variable.
518 * @param less Must return true if the specified key is less than the key of
519 *   the node, otherwise false.
520 *
521 * @retval true The inserted node is the new minimum node according to the
522 *   specified less order function.
523 * @retval false The inserted node is not the new minimum node according to the
524 *   specified less order function.
525 */
526static inline bool _RBTree_Insert_inline(
527  RBTree_Control *the_rbtree,
528  RBTree_Node    *the_node,
529  const void     *key,
530  bool         ( *less )( const void *, const RBTree_Node * )
531)
532{
533  RBTree_Node **link;
534  RBTree_Node  *parent;
535  bool          is_new_minimum;
536
537  link = _RBTree_Root_reference( the_rbtree );
538  parent = NULL;
539  is_new_minimum = true;
540
541  while ( *link != NULL ) {
542    parent = *link;
543
544    if ( ( *less )( key, parent ) ) {
545      link = _RBTree_Left_reference( parent );
546    } else {
547      link = _RBTree_Right_reference( parent );
548      is_new_minimum = false;
549    }
550  }
551
552  _RBTree_Add_child( the_node, parent, link );
553  _RBTree_Insert_color( the_rbtree, the_node );
554  return is_new_minimum;
555}
556
557/**
558 * @brief Finds an object in the red-black tree with the specified key.
559 *
560 * @param the_rbtree The red-black tree control.
561 * @param key The key to look after.
562 * @param equal Must return true if the specified key equals the key of the
563 *   node, otherwise false.
564 * @param less Must return true if the specified key is less than the key of
565 *   the node, otherwise false.
566 * @param map In case a node with the specified key is found, then this
567 *   function is called to map the node to the object returned.  Usually it
568 *   performs some offset operation via RTEMS_CONTAINER_OF() to map the node to
569 *   its containing object.  Thus, the return type is a void pointer and not a
570 *   red-black tree node.
571 *
572 * @retval object An object with the specified key.
573 * @retval NULL No object with the specified key exists in the red-black tree.
574 */
575static inline void *_RBTree_Find_inline(
576  const RBTree_Control *the_rbtree,
577  const void           *key,
578  bool               ( *equal )( const void *, const RBTree_Node * ),
579  bool               ( *less )( const void *, const RBTree_Node * ),
580  void              *( *map )( RBTree_Node * )
581)
582{
583  RBTree_Node * const *link;
584  RBTree_Node         *parent;
585
586  link = _RBTree_Root_const_reference( the_rbtree );
587  parent = NULL;
588
589  while ( *link != NULL ) {
590    parent = *link;
591
592    if ( ( *equal )( key, parent ) ) {
593      return ( *map )( parent );
594    } else if ( ( *less )( key, parent ) ) {
595      link = _RBTree_Left_reference( parent );
596    } else {
597      link = _RBTree_Right_reference( parent );
598    }
599  }
600
601  return NULL;
602}
603
604/**
605 * @brief Returns the container of the first node of the specified red-black
606 * tree in postorder.
607 *
608 * Postorder traversal may be used to delete all nodes of a red-black tree.
609 *
610 * @param the_rbtree The red-black tree control.
611 * @param offset The offset to the red-black tree node in the container structure.
612 *
613 * @retval container The container of the first node of the specified red-black
614 *   tree in postorder.
615 * @retval NULL The red-black tree is empty.
616 *
617 * @see _RBTree_Postorder_next().
618 *
619 * @code
620 * #include <rtems/score/rbtree.h>
621 *
622 * typedef struct {
623 *   int         data;
624 *   RBTree_Node Node;
625 * } Container_Control;
626 *
627 * void visit( Container_Control *the_container );
628 *
629 * void postorder_traversal( RBTree_Control *the_rbtree )
630 * {
631 *   Container_Control *the_container;
632 *
633 *   the_container = _RBTree_Postorder_first(
634 *     the_rbtree,
635 *     offsetof( Container_Control, Node )
636 *   );
637 *
638 *   while ( the_container != NULL ) {
639 *     visit( the_container );
640 *
641 *     the_container = _RBTree_Postorder_next(
642 *       &the_container->Node,
643 *       offsetof( Container_Control, Node )
644 *     );
645 *   }
646 * }
647 * @endcode
648 */
649void *_RBTree_Postorder_first(
650  const RBTree_Control *the_rbtree,
651  size_t                offset
652);
653
654/**
655 * @brief Returns the container of the next node in postorder.
656 *
657 * @param the_node The red-black tree node.  The node must not be NULL.
658 * @param offset The offset to the red-black tree node in the container structure.
659 *
660 * @retval container The container of the next node in postorder.
661 * @retval NULL The node is NULL or there is no next node in postorder.
662 *
663 * @see _RBTree_Postorder_first().
664 */
665void *_RBTree_Postorder_next(
666  const RBTree_Node *the_node,
667  size_t             offset
668);
669
670/** @} */
671
672#ifdef __cplusplus
673}
674#endif
675
676#endif
677/* end of include file */
Note: See TracBrowser for help on using the repository browser.