Ticket #1886: rbtree_duplicate_key3.diff
File rbtree_duplicate_key3.diff, 17.9 KB (added by Petr Benes, on 08/09/11 at 13:03:01) |
---|
-
cpukit/sapi/include/rtems/rbtree.h
diff --git a/cpukit/sapi/include/rtems/rbtree.h b/cpukit/sapi/include/rtems/rbtree.h index 6a75fc4..42811ca 100644
a b typedef RBTree_Node rtems_rbtree_node; 43 43 typedef RBTree_Control rtems_rbtree_control; 44 44 45 45 /** 46 * @typedef rtems_rbtree_compare_function 47 * 48 * This type defines function pointers for user-provided comparison 49 * function. The function compares two nodes in order to determine 50 * the order in a red-black tree. 51 */ 52 typedef RBTree_Compare_function rtems_rbtree_compare_function; 53 54 /** 55 * @typedef rtems_rbtree_unique 56 * 57 * This enum type defines whether the tree can contain nodes with 58 * duplicate keys. 59 */ 60 typedef enum { 61 /** The tree is not unique, insertion of duplicate keys is performed 62 * in a FIFO manner. */ 63 RTEMS_RBTREE_DUPLICATE = false, 64 /** The tree is unique, insertion of duplicate key is refused. */ 65 RTEMS_RBTREE_UNIQUE = true 66 } rtems_rbtree_unique; 67 68 /** 46 69 * @brief RBTree initializer for an empty rbtree with designator @a name. 47 70 */ 48 71 #define RTEMS_RBTREE_INITIALIZER_EMPTY(name) \ -
cpukit/sapi/inline/rtems/rbtree.inl
diff --git a/cpukit/sapi/inline/rtems/rbtree.inl b/cpukit/sapi/inline/rtems/rbtree.inl index f5b28e4..234ae90 100644
a b 35 35 * @a starting_address. Each node is of @a node_size bytes. 36 36 */ 37 37 RTEMS_INLINE_ROUTINE void rtems_rbtree_initialize( 38 rtems_rbtree_control *the_rbtree, 39 void *compare_function, 40 void *starting_address, 41 size_t number_nodes, 42 size_t node_size 38 rtems_rbtree_control *the_rbtree, 39 rtems_rbtree_compare_function compare_function, 40 void *starting_address, 41 size_t number_nodes, 42 size_t node_size, 43 rtems_rbtree_unique is_unique 43 44 ) 44 45 { 45 46 _RBTree_Initialize( the_rbtree, compare_function, starting_address, 46 number_nodes, node_size );47 number_nodes, node_size, is_unique); 47 48 } 48 49 49 50 /** … … RTEMS_INLINE_ROUTINE void rtems_rbtree_initialize( 52 53 * This routine initializes @a the_rbtree to contain zero nodes. 53 54 */ 54 55 RTEMS_INLINE_ROUTINE void rtems_rbtree_initialize_empty( 55 rtems_rbtree_control *the_rbtree, 56 void *compare_function 56 rtems_rbtree_control *the_rbtree, 57 rtems_rbtree_compare_function compare_function, 58 rtems_rbtree_unique is_unique 57 59 ) 58 60 { 59 _RBTree_Initialize_empty( the_rbtree, compare_function );61 _RBTree_Initialize_empty( the_rbtree, compare_function, is_unique ); 60 62 } 61 63 62 64 /** … … RTEMS_INLINE_ROUTINE bool rtems_rbtree_is_root( 257 259 * This function returns a pointer to the node having key equal to the key 258 260 * of @a the_node if it exists within @a the_rbtree, and NULL if not. 259 261 * @a the_node has to be made up before a search. 262 * 263 * @note If the tree is not unique and contains duplicate keys, the set 264 * of duplicate keys acts as FIFO. 260 265 */ 261 266 RTEMS_INLINE_ROUTINE rtems_rbtree_node* rtems_rbtree_find( 262 267 rtems_rbtree_control *the_rbtree, … … RTEMS_INLINE_ROUTINE rtems_rbtree_control *rtems_rbtree_find_header( 382 387 * 383 388 * This routine inserts @a the_node on @a the_rbtree. 384 389 * It disables interrupts to ensure the atomicity of the insert operation. 390 * 391 * @retval 0 Successfully inserted. 392 * @retval -1 NULL @a the_node. 393 * @retval RBTree_Node* if one with equal key to the key of @a the_node exists 394 * in an unique @a the_rbtree. 385 395 */ 386 RTEMS_INLINE_ROUTINE voidrtems_rbtree_insert(396 RTEMS_INLINE_ROUTINE rtems_rbtree_node *rtems_rbtree_insert( 387 397 rtems_rbtree_control *the_rbtree, 388 398 rtems_rbtree_node *the_node 389 399 ) 390 400 { 391 _RBTree_Insert( the_rbtree, the_node ); 401 return _RBTree_Insert( the_rbtree, the_node ); 402 } 403 404 /** @brief Determines whether the tree is unique 405 */ 406 RTEMS_INLINE_ROUTINE rtems_rbtree_unique rtems_rbtree_is_unique( 407 rtems_rbtree_control *the_rbtree 408 ) 409 { 410 return( _RBTree_Is_unique(the_rbtree) ); 392 411 } 393 412 394 413 #endif -
cpukit/score/include/rtems/score/rbtree.h
diff --git a/cpukit/score/include/rtems/score/rbtree.h b/cpukit/score/include/rtems/score/rbtree.h index a0c6e2c..e32ec21 100644
a b typedef enum { 100 100 } RBTree_Direction; 101 101 102 102 /** 103 * This type defines function pointers for user-provided comparison 104 * function. The function compares two nodes in order to determine 105 * the order in a red-black tree. 106 */ 107 typedef int (*RBTree_Compare_function)( 108 RBTree_Node *node1, 109 RBTree_Node *node2 110 ); 111 112 /** 103 113 * @struct RBTree_Control 104 114 * 105 115 * This is used to manage a RBT. A rbtree consists of a tree of zero or more … … typedef struct { 126 136 /** This points to the min and max nodes of this RBT. */ 127 137 RBTree_Node *first[2]; 128 138 /** 129 * Comparison function pointer. Keys to compare ha sto be found139 * Comparison function pointer. Keys to compare have to be found 130 140 * inside to maintain generality. It has to return 1 if first node 131 141 * has higher key than second, -1 if lower, 0 if equal. 132 142 */ 133 int (*compare_function) (RBTree_Node*, RBTree_Node*); 143 RBTree_Compare_function compare_function; 144 /** Determines whether the tree accepts duplicate keys. */ 145 bool is_unique; 134 146 } RBTree_Control; 135 147 136 148 /** … … typedef struct { 142 154 .root = NULL, \ 143 155 .first[0] = NULL, \ 144 156 .first[1] = NULL, \ 145 .compare_function = NULL \ 157 .compare_function = NULL, \ 158 .is_unique = 0 \ 146 159 } 147 160 148 161 /** … … RBTree_Node name = RBTREE_NODE_INITIALIZER_EMPTY(name) 176 189 * @a starting_address. Each node is of @a node_size bytes. 177 190 */ 178 191 void _RBTree_Initialize( 179 RBTree_Control *the_rbtree, 180 void *compare_function, 181 void *starting_address, 182 size_t number_nodes, 183 size_t node_size 192 RBTree_Control *the_rbtree, 193 RBTree_Compare_function compare_function, 194 void *starting_address, 195 size_t number_nodes, 196 size_t node_size, 197 bool is_unique 184 198 ); 185 199 186 200 /** … … RBTree_Control *_RBTree_Find_header( 247 261 * 248 262 * @retval 0 Successfully inserted. 249 263 * @retval -1 NULL @a the_node. 250 * @retval RBTree_Node* if one with equal value to @a the_node ->valueexists251 * in @a the_rbtree.264 * @retval RBTree_Node* if one with equal value to @a the_node 's key exists 265 * in an unique @a the_rbtree. 252 266 * 253 267 * @note It does NOT disable interrupts to ensure the atomicity 254 268 * of the extract operation. … … RBTree_Node *_RBTree_Insert_unprotected( 263 277 * 264 278 * This routine inserts @a the_node on the tree @a the_rbtree. 265 279 * 280 * @retval 0 Successfully inserted. 281 * @retval -1 NULL @a the_node. 282 * @retval RBTree_Node* if one with equal value to @a the_node 's key exists 283 * in an unique @a the_rbtree. 284 * 266 285 * @note It disables interrupts to ensure the atomicity 267 286 * of the extract operation. 268 287 */ 269 void_RBTree_Insert(288 RBTree_Node *_RBTree_Insert( 270 289 RBTree_Control *the_rbtree, 271 290 RBTree_Node *the_node 272 291 ); -
cpukit/score/inline/rtems/score/rbtree.inl
diff --git a/cpukit/score/inline/rtems/score/rbtree.inl b/cpukit/score/inline/rtems/score/rbtree.inl index 8e1c66e..e73a80b 100644
a b RTEMS_INLINE_ROUTINE bool _RBTree_Is_root( 235 235 * This routine initializes @a the_rbtree to contain zero nodes. 236 236 */ 237 237 RTEMS_INLINE_ROUTINE void _RBTree_Initialize_empty( 238 RBTree_Control *the_rbtree, 239 void *compare_function 238 RBTree_Control *the_rbtree, 239 RBTree_Compare_function compare_function, 240 bool is_unique 240 241 ) 241 242 { 242 243 the_rbtree->permanent_null = NULL; … … RTEMS_INLINE_ROUTINE void _RBTree_Initialize_empty( 244 245 the_rbtree->first[0] = NULL; 245 246 the_rbtree->first[1] = NULL; 246 247 the_rbtree->compare_function = compare_function; 248 the_rbtree->is_unique = is_unique; 247 249 } 248 250 249 251 /** @brief Return a pointer to node's grandparent … … RTEMS_INLINE_ROUTINE RBTree_Control *_RBTree_Find_header_unprotected( 317 319 * This function returns a pointer to the node in @a the_rbtree 318 320 * having key equal to key of @a the_node if it exists, 319 321 * and NULL if not. @a the_node has to be made up before a search. 322 * 323 * @note If the tree is not unique and contains duplicate keys, the set 324 * of duplicate keys acts as FIFO. 320 325 */ 321 326 RTEMS_INLINE_ROUTINE RBTree_Node *_RBTree_Find_unprotected( 322 327 RBTree_Control *the_rbtree, … … RTEMS_INLINE_ROUTINE RBTree_Node *_RBTree_Find_unprotected( 324 329 ) 325 330 { 326 331 RBTree_Node* iter_node = the_rbtree->root; 332 RBTree_Node* found = NULL; 327 333 int compare_result; 328 334 while (iter_node) { 329 335 compare_result = the_rbtree->compare_function(the_node, iter_node); 330 336 if (compare_result == 0) { 331 return(iter_node); 337 found = iter_node; 338 if ( the_rbtree->is_unique ) 339 break; 332 340 } 333 341 334 RBTree_Direction dir = (compare_result != -1);342 RBTree_Direction dir = (compare_result == 1); 335 343 iter_node = iter_node->child[dir]; 336 344 } /* while(iter_node) */ 337 345 338 return 0;346 return found; 339 347 } 340 348 341 349 /** @brief Find the nodes in-order predecessor … … RTEMS_INLINE_ROUTINE void _RBTree_Rotate( 428 436 RBTree_Node *c; 429 437 if (the_node == NULL) return; 430 438 if (the_node->child[(1-dir)] == NULL) return; 431 432 439 433 440 c = the_node->child[(1-dir)]; 434 441 the_node->child[(1-dir)] = c->child[dir]; … … RTEMS_INLINE_ROUTINE void _RBTree_Rotate( 443 450 c->parent = the_node->parent; 444 451 the_node->parent = c; 445 452 } 453 454 /** @brief Determines whether the tree is unique 455 */ 456 RTEMS_INLINE_ROUTINE bool _RBTree_Is_unique( 457 RBTree_Control *the_rbtree 458 ) 459 { 460 return( the_rbtree && the_rbtree->is_unique ); 461 } 446 462 /**@}*/ 447 463 448 464 #endif -
cpukit/score/src/rbtree.c
diff --git a/cpukit/score/src/rbtree.c b/cpukit/score/src/rbtree.c index cc20361..cc8accf 100644
a b 32 32 */ 33 33 34 34 void _RBTree_Initialize( 35 RBTree_Control *the_rbtree, 36 void *compare_function, 37 void *starting_address, 38 size_t number_nodes, 39 size_t node_size 35 RBTree_Control *the_rbtree, 36 RBTree_Compare_function compare_function, 37 void *starting_address, 38 size_t number_nodes, 39 size_t node_size, 40 bool is_unique 40 41 ) 41 42 { 42 43 size_t count; … … void _RBTree_Initialize( 46 47 if (!the_rbtree) return; 47 48 48 49 /* could do sanity checks here */ 49 _RBTree_Initialize_empty(the_rbtree, compare_function );50 _RBTree_Initialize_empty(the_rbtree, compare_function, is_unique); 50 51 51 52 count = number_nodes; 52 53 next = starting_address; -
cpukit/score/src/rbtreeinsert.c
diff --git a/cpukit/score/src/rbtreeinsert.c b/cpukit/score/src/rbtreeinsert.c index c2c60ed..7ae8d71 100644
a b void _RBTree_Validate_insert_unprotected( 72 72 * @retval 0 Successfully inserted. 73 73 * @retval -1 NULL @a the_node. 74 74 * @retval RBTree_Node* if one with equal key to the key of @a the_node exists 75 * in @a the_rbtree.75 * in an unique @a the_rbtree. 76 76 * 77 77 * @note It does NOT disable interrupts to ensure the atomicity 78 78 * of the extract operation. … … RBTree_Node *_RBTree_Insert_unprotected( 97 97 /* typical binary search tree insert, descend tree to leaf and insert */ 98 98 while (iter_node) { 99 99 compare_result = the_rbtree->compare_function(the_node, iter_node); 100 if ( !compare_result ) return iter_node; 100 if ( the_rbtree->is_unique && !compare_result ) 101 return iter_node; 101 102 RBTree_Direction dir = (compare_result != -1); 102 103 if (!iter_node->child[dir]) { 103 104 the_node->child[RBT_LEFT] = the_node->child[RBT_RIGHT] = NULL; … … RBTree_Node *_RBTree_Insert_unprotected( 138 139 * only case 139 140 */ 140 141 141 void_RBTree_Insert(142 RBTree_Node *_RBTree_Insert( 142 143 RBTree_Control *tree, 143 144 RBTree_Node *node 144 145 ) … … void _RBTree_Insert( 146 147 ISR_Level level; 147 148 148 149 _ISR_Disable( level ); 149 _RBTree_Insert_unprotected( tree, node );150 return _RBTree_Insert_unprotected( tree, node ); 150 151 _ISR_Enable( level ); 151 152 } -
testsuites/sptests/sprbtree01/init.c
diff --git a/testsuites/sptests/sprbtree01/init.c b/testsuites/sptests/sprbtree01/init.c index df83d41..f9f0d22 100644
a b rtems_task Init( 100 100 puts( "\n\n*** TEST OF RTEMS RBTREE API ***" ); 101 101 102 102 puts( "Init - Initialize rbtree empty" ); 103 rtems_rbtree_initialize_empty( &rbtree1, &test_compare_function ); 104 103 rtems_rbtree_initialize_empty( &rbtree1, &test_compare_function, 104 RTEMS_RBTREE_UNIQUE ); 105 106 if ( !rtems_rbtree_is_unique( &rbtree1 ) ) 107 puts( "INIT - FAILED IS UNIQUE CHECK" ); 108 if ( rtems_rbtree_is_unique( NULL ) ) 109 puts( "INIT - FAILED IS UNIQUE CHECK" ); 110 105 111 /* verify that the rbtree insert work */ 106 112 puts( "INIT - Verify rtems_rbtree_insert with two nodes" ); 107 113 node1.id = 1; … … rtems_task Init( 111 117 rtems_rbtree_insert( &rbtree1, &node1.Node ); 112 118 rtems_rbtree_insert( &rbtree1, &node2.Node ); 113 119 114 p = _RBTree_Insert_unprotected( &rbtree1, NULL );120 p = rtems_rbtree_insert( &rbtree1, NULL ); 115 121 if (p != (void *)(-1)) 116 122 puts( "INIT - FAILED NULL NODE INSERT" ); 117 123 … … rtems_task Init( 149 155 puts("INIT - Verify rtems_rbtree_insert with the same value twice"); 150 156 node2.key = node1.key; 151 157 rtems_rbtree_insert(&rbtree1, &node1.Node); 152 rtems_rbtree_insert(&rbtree1, &node2.Node); 158 p = rtems_rbtree_insert(&rbtree1, &node2.Node); 159 160 if (p != &node1.Node) 161 puts( "INIT - FAILED DUPLICATE INSERT" ); 162 153 163 for ( p = rtems_rbtree_get_min(&rbtree1), id = 1 ; p ; 154 164 p = rtems_rbtree_get_min(&rbtree1) , id++ ) { 155 165 test_node *t = rtems_rbtree_container_of(p,test_node,Node); … … rtems_task Init( 527 537 node_array[i].key = i; 528 538 } 529 539 rtems_rbtree_initialize( &rbtree1, &test_compare_function, 530 &node_array[0].Node, 100, sizeof(test_node)); 540 &node_array[0].Node, 100, 541 sizeof(test_node), RTEMS_RBTREE_UNIQUE ); 531 542 532 543 puts( "INIT - Removing 100 nodes" ); 533 544 … … rtems_task Init( 553 564 rtems_test_exit(0); 554 565 } 555 566 567 /* Initialize the tree for duplicate keys */ 568 puts( "Init - Initialize duplicate rbtree empty" ); 569 rtems_rbtree_initialize_empty( &rbtree1, &test_compare_function, 570 RTEMS_RBTREE_DUPLICATE ); 571 572 if ( rtems_rbtree_is_unique( &rbtree1 ) ) 573 puts( "INIT - FAILED IS UNIQUE CHECK" ); 574 if ( rtems_rbtree_is_unique( NULL ) ) 575 puts( "INIT - FAILED IS UNIQUE CHECK" ); 576 577 puts( "INIT - Verify rtems_rbtree_insert with 100 nodes value [0,99]" ); 578 for (i = 0; i < 100; i++) { 579 node_array[i].id = i; 580 node_array[i].key = i%5; 581 rtems_rbtree_insert( &rbtree1, &node_array[i].Node ); 582 583 if (!rb_assert(rbtree1.root) ) 584 puts( "INIT - FAILED TREE CHECK" ); 585 } 586 587 puts( "INIT - Verify rtems_rbtree_find in a duplicate tree" ); 588 search_node.key = 2; 589 p = rtems_rbtree_find(&rbtree1, &search_node.Node); 590 if(rtems_rbtree_container_of(p,test_node,Node)->id != 2) { 591 puts ("INIT - ERROR ON RBTREE ID MISMATCH"); 592 rtems_test_exit(0); 593 } 594 595 puts( "INIT - Removing 100 nodes" ); 596 597 for ( p = rtems_rbtree_get_min(&rbtree1), id = 0 ; p ; 598 p = rtems_rbtree_get_min(&rbtree1) , id++ ) { 599 test_node *t = rtems_rbtree_container_of(p,test_node,Node); 600 if ( id > 99 ) { 601 puts( "INIT - TOO MANY NODES ON RBTREE" ); 602 rtems_test_exit(0); 603 } 604 if ( t->id != ( ((id*5)%100) + (id/20) ) ) { 605 puts( "INIT - ERROR ON RBTREE ID MISMATCH" ); 606 rtems_test_exit(0); 607 } 608 609 if (!rb_assert(rbtree1.root) ) 610 puts( "INIT - FAILED TREE CHECK" ); 611 } 612 613 if(!rtems_rbtree_is_empty(&rbtree1)) { 614 puts( "INIT - TREE NOT EMPTY" ); 615 rtems_test_exit(0); 616 } 617 618 puts( "INIT - Verify rtems_rbtree_insert with 100 nodes value [99,0]" ); 619 for (i = 0; i < 100; i++) { 620 node_array[i].id = 99-i; 621 node_array[i].key = (99-i)%5; 622 rtems_rbtree_insert( &rbtree1, &node_array[i].Node ); 623 624 if (!rb_assert(rbtree1.root) ) 625 puts( "INIT - FAILED TREE CHECK" ); 626 } 627 628 puts( "INIT - Verify rtems_rbtree_find in a duplicate tree" ); 629 search_node.key = 2; 630 p = rtems_rbtree_find(&rbtree1, &search_node.Node); 631 if(rtems_rbtree_container_of(p,test_node,Node)->id != 97) { 632 puts ("INIT - ERROR ON RBTREE ID MISMATCH"); 633 rtems_test_exit(0); 634 } 635 636 puts( "INIT - Removing 100 nodes" ); 637 638 for ( p = rtems_rbtree_get_min(&rbtree1), id = 0 ; p ; 639 p = rtems_rbtree_get_min(&rbtree1) , id++ ) { 640 test_node *t = rtems_rbtree_container_of(p,test_node,Node); 641 if ( id > 99 ) { 642 puts( "INIT - TOO MANY NODES ON RBTREE" ); 643 rtems_test_exit(0); 644 } 645 if ( t->id != ( (((99-id)*5)%100) + (id/20) ) ) { 646 puts( "INIT - ERROR ON RBTREE ID MISMATCH" ); 647 rtems_test_exit(0); 648 } 649 650 if (!rb_assert(rbtree1.root) ) 651 puts( "INIT - FAILED TREE CHECK" ); 652 } 653 654 if(!rtems_rbtree_is_empty(&rbtree1)) { 655 puts( "INIT - TREE NOT EMPTY" ); 656 rtems_test_exit(0); 657 } 658 556 659 puts( "*** END OF RTEMS RBTREE API TEST ***" ); 557 660 rtems_test_exit(0); 558 661 } -
testsuites/sptests/sprbtree01/sprbtree01.scn
diff --git a/testsuites/sptests/sprbtree01/sprbtree01.scn b/testsuites/sptests/sprbtree01/sprbtree01.scn index 3060a96..0bf2007 100644
a b INIT - Insert 20 random numbers 24 24 INIT - Removing 20 nodes 25 25 INIT - Verify rtems_rbtree_initialize with 100 nodes value [0,99] 26 26 INIT - Removing 100 nodes 27 Init - Initialize duplicate rbtree empty 28 INIT - Verify rtems_rbtree_insert with 100 nodes value [0,99] 29 INIT - Verify rtems_rbtree_find in a duplicate tree 30 INIT - Removing 100 nodes 31 INIT - Verify rtems_rbtree_insert with 100 nodes value [99,0] 32 INIT - Verify rtems_rbtree_find in a duplicate tree 33 INIT - Removing 100 nodes 27 34 *** END OF RTEMS RBTREE API TEST ***