Ticket #1886: rbtree_duplicate_key.diff
File rbtree_duplicate_key.diff, 15.7 KB (added by Petr Benes, on 08/03/11 at 14:17:44) |
---|
-
cpukit/sapi/include/rtems/rbtree.h
diff --git a/cpukit/sapi/include/rtems/rbtree.h b/cpukit/sapi/include/rtems/rbtree.h index 6a75fc4..dd340bb 100644
a b typedef RBTree_Node rtems_rbtree_node; 43 43 typedef RBTree_Control rtems_rbtree_control; 44 44 45 45 /** 46 * This enum type defines whether the tree can contain nodes with 47 * duplicate keys. 48 */ 49 typedef enum { 50 /** The tree is not unique, insertion of duplicate keys is performed 51 * in a FIFO manner. */ 52 RTEMS_RBTREE_DUPLICATE = false, 53 /** The tree is unique, insertion of duplicate key is refused. */ 54 RTEMS_RBTREE_UNIQUE = true 55 } rtems_rbtree_unique; 56 57 /** 46 58 * @brief RBTree initializer for an empty rbtree with designator @a name. 47 59 */ 48 60 #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 ac513be..082e441 100644
a b RTEMS_INLINE_ROUTINE void rtems_rbtree_initialize( 39 39 void *compare_function, 40 40 void *starting_address, 41 41 size_t number_nodes, 42 size_t node_size 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( 53 54 */ 54 55 RTEMS_INLINE_ROUTINE void rtems_rbtree_initialize_empty( 55 56 rtems_rbtree_control *the_rbtree, 56 void *compare_function 57 void *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 aa2b8bb..f6e17fe 100644
a b typedef struct { 131 131 * has higher key than second, -1 if lower, 0 if equal. 132 132 */ 133 133 int (*compare_function) (RBTree_Node*, RBTree_Node*); 134 /** Determines whether the tree accepts duplicate keys. */ 135 bool is_unique; 134 136 } RBTree_Control; 135 137 136 138 /** … … typedef struct { 142 144 .root = NULL, \ 143 145 .first[0] = NULL, \ 144 146 .first[1] = NULL, \ 145 .compare_function = NULL \ 147 .compare_function = NULL, \ 148 .is_uinque = 0 \ 146 149 } 147 150 148 151 /** … … void _RBTree_Initialize( 180 183 void *compare_function, 181 184 void *starting_address, 182 185 size_t number_nodes, 183 size_t node_size 186 size_t node_size, 187 bool is_unique 184 188 ); 185 189 186 190 /** … … RBTree_Control *_RBTree_Find_header( 247 251 * 248 252 * @retval 0 Successfully inserted. 249 253 * @retval -1 NULL @a the_node. 250 * @retval RBTree_Node* if one with equal value to @a the_node ->valueexists251 * in @a the_rbtree.254 * @retval RBTree_Node* if one with equal value to @a the_node 's key exists 255 * in an unique @a the_rbtree. 252 256 * 253 257 * @note It does NOT disable interrupts to ensure the atomicity 254 258 * of the extract operation. … … RBTree_Node *_RBTree_Insert_unprotected( 263 267 * 264 268 * This routine inserts @a the_node on the tree @a the_rbtree. 265 269 * 270 * @retval 0 Successfully inserted. 271 * @retval -1 NULL @a the_node. 272 * @retval RBTree_Node* if one with equal value to @a the_node 's key exists 273 * in an unique @a the_rbtree. 274 * 266 275 * @note It disables interrupts to ensure the atomicity 267 276 * of the extract operation. 268 277 */ 269 void_RBTree_Insert(278 RBTree_Node *_RBTree_Insert( 270 279 RBTree_Control *the_rbtree, 271 280 RBTree_Node *the_node 272 281 ); -
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 f882cf1..def8f77 100644
a b RTEMS_INLINE_ROUTINE bool _RBTree_Is_root( 236 236 */ 237 237 RTEMS_INLINE_ROUTINE void _RBTree_Initialize_empty( 238 238 RBTree_Control *the_rbtree, 239 void *compare_function 239 void *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* left_child; 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 if ( !the_rbtree->is_unique ) { 338 while ( (left_child = iter_node->child[RBT_LEFT]) && 339 the_rbtree->compare_function(the_node, left_child) == 0 ) 340 iter_node = left_child; 341 } 342 return(iter_node); 332 343 } 333 344 334 345 RBTree_Direction dir = (compare_result != -1); … … RTEMS_INLINE_ROUTINE void _RBTree_Rotate( 428 439 RBTree_Node *c; 429 440 if (the_node == NULL) return; 430 441 if (the_node->child[(1-dir)] == NULL) return; 431 432 442 433 443 c = the_node->child[(1-dir)]; 434 444 the_node->child[(1-dir)] = c->child[dir]; … … RTEMS_INLINE_ROUTINE void _RBTree_Rotate( 443 453 c->parent = the_node->parent; 444 454 the_node->parent = c; 445 455 } 456 457 /** @brief Determines whether the tree is unique 458 */ 459 RTEMS_INLINE_ROUTINE bool _RBTree_Is_unique( 460 RBTree_Control *the_rbtree 461 ) 462 { 463 return( the_rbtree && the_rbtree->is_unique ); 464 } 446 465 /**@}*/ 447 466 448 467 #endif -
cpukit/score/src/rbtree.c
diff --git a/cpukit/score/src/rbtree.c b/cpukit/score/src/rbtree.c index 7b44ba0..d7d68fe 100644
a b void _RBTree_Initialize( 35 35 RBTree_Control *the_rbtree, 36 36 void *compare_function, 37 37 void *starting_address, 38 size_t number_nodes, 39 size_t node_size 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 58ccc6a..955dfcd 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 e436b12..dbb1fa0 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 ***