1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0 3 * 4 * This file is provided under a dual BSD/GPLv2 license. When using or 5 * redistributing this file, you may do so under either license. 6 * 7 * GPL LICENSE SUMMARY 8 * 9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of version 2 of the GNU General Public License as 13 * published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 23 * The full GNU General Public License is included in this distribution 24 * in the file called LICENSE.GPL. 25 * 26 * BSD LICENSE 27 * 28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 29 * All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 35 * * Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * * Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in 39 * the documentation and/or other materials provided with the 40 * distribution. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 45 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 46 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 48 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 */ 54 /** 55 * @file 56 * 57 * @brief This file contains the interface to the abstract list class. 58 * This class will allow for the same item to occur multiple times in 59 * a list or multiple lists. It will provide an interface that is 60 * similar to the C++ standard template list interface. 61 * Methods Provided: 62 * - sci_abstract_list_front() 63 * - sci_abstract_list_back() 64 * - sci_abstract_list_is_empty() 65 * - sci_abstract_list_size() 66 * - sci_abstract_list_print() 67 * - sci_abstract_list_find() 68 * - sci_abstract_list_popback() 69 * - sci_abstract_list_popfront() 70 * - sci_abstract_list_erase() 71 * - sci_abstract_list_pushback() 72 * - sci_abstract_list_pushfront() 73 * - sci_abstract_list_get_object() 74 * - sci_abstract_list_get_next() 75 * - sci_abstract_list_insert() UNIMPLEMENTED 76 * - sci_abstract_list_clear() 77 */ 78 79 #ifndef _SCI_ABSTRACT_LIST_H_ 80 #define _SCI_ABSTRACT_LIST_H_ 81 82 //****************************************************************************** 83 //* 84 //* I N C L U D E S 85 //* 86 //****************************************************************************** 87 88 #include <dev/isci/scil/sci_types.h> 89 90 //****************************************************************************** 91 //* 92 //* C O N S T A N T S 93 //* 94 //****************************************************************************** 95 96 //****************************************************************************** 97 //* 98 //* T Y P E S 99 //* 100 //****************************************************************************** 101 102 /** 103 * @struct SCI_ABSTRACT_ELEMENT 104 * 105 * @brief This object represents an element of a abstract list. 106 * NOTE: This structure does not evenly align on a cache line 107 * boundary. If SSP specific code ends up using this list, 108 * then it may be a good idea to force the alignment. Now 109 * it is more important to save the space. 110 */ 111 typedef struct SCI_ABSTRACT_ELEMENT 112 { 113 /** 114 * This field points to the next item in the abstract_list. 115 */ 116 struct SCI_ABSTRACT_ELEMENT * next_p; 117 118 /** 119 * This field points to the previous item in the abstract_list. 120 */ 121 struct SCI_ABSTRACT_ELEMENT * previous_p; 122 123 /** 124 * This field points to the object the list is managing (i.e. the thing 125 * being listed). 126 */ 127 void * object_p; 128 129 } SCI_ABSTRACT_ELEMENT_T; 130 131 /** 132 * @struct SCI_ABSTRACT_ELEMENT_LIST 133 * 134 * @brief This object represents an element list object. It can have 135 * elements added and removed from it. 136 */ 137 typedef struct SCI_ABSTRACT_ELEMENT_LIST 138 { 139 /** 140 * Pointer to the front (head) of the list. 141 */ 142 SCI_ABSTRACT_ELEMENT_T * front_p; 143 144 /** 145 * Pointer to the back (tail) of the list. 146 */ 147 SCI_ABSTRACT_ELEMENT_T * back_p; 148 149 /** 150 * This field depicts the number of elements in this list. 151 * NOTE: It is possible to remove this field and replace it with a 152 * linear walking of the list to determine the size, but since 153 * there aren't many lists in the system we don't utilize much 154 * space. 155 */ 156 U32 size; 157 158 } SCI_ABSTRACT_ELEMENT_LIST_T; 159 160 /** 161 * @struct SCI_ABSTRACT_ELEMENT_POOL 162 * 163 * @brief This structure provides the pool of free abstract elements to be 164 * utilized by an SCI_ABSTRACT_LIST. 165 */ 166 typedef struct SCI_ABSTRACT_ELEMENT_POOL 167 { 168 /** 169 * Pointer to an array of elements to be managed by this pool. This 170 * array acts as the memory store for the elements in the free pool or 171 * allocated out of the pool into an SCI_ABSTRACT_LIST. 172 */ 173 SCI_ABSTRACT_ELEMENT_T * elements; 174 175 /** 176 * This field contains the maximum number of free elements for the pool. 177 * It is set at creation of the pool and should not be changed afterward. 178 */ 179 U32 max_elements; 180 181 /** 182 * Pointer to the list of free elements that can be allocated from 183 * the pool. 184 */ 185 struct SCI_ABSTRACT_ELEMENT_LIST free_list; 186 187 } SCI_ABSTRACT_ELEMENT_POOL_T; 188 189 /** 190 * @struct SCI_ABSTRACT_LIST 191 * 192 * @brief This object provides the ability to queue any type of object or 193 * even the same object multiple times. The object must be provided 194 * an element pool from which to draw free elements. 195 */ 196 typedef struct SCI_ABSTRACT_LIST 197 { 198 /** 199 * This represents the elements currently managed by the list. 200 */ 201 SCI_ABSTRACT_ELEMENT_LIST_T elements; 202 203 /** 204 * This field contains elements that are currently available for 205 * allocation into the list of elements; 206 */ 207 SCI_ABSTRACT_ELEMENT_POOL_T * free_pool; 208 209 } SCI_ABSTRACT_LIST_T; 210 211 //****************************************************************************** 212 //* 213 //* P R O T E C T E D M E T H O D S 214 //* 215 //****************************************************************************** 216 217 void sci_abstract_element_pool_construct( 218 SCI_ABSTRACT_ELEMENT_POOL_T * pool, 219 SCI_ABSTRACT_ELEMENT_T * list_elements, 220 int element_count 221 ); 222 223 void sci_abstract_list_construct( 224 SCI_ABSTRACT_LIST_T * list, 225 SCI_ABSTRACT_ELEMENT_POOL_T * free_pool 226 ); 227 228 229 230 #ifdef USE_ABSTRACT_LIST_FUNCTIONS 231 //****************************************************************************** 232 //* 233 //* P U B L I C M E T H O D S 234 //* 235 //****************************************************************************** 236 237 /** 238 * Simply return the front element pointer of the list. This returns an element 239 * element as opposed to what the element is pointing to. 240 */ 241 SCI_ABSTRACT_ELEMENT_T * sci_abstract_list_get_front( 242 SCI_ABSTRACT_LIST_T * list_p 243 ); 244 245 246 /** 247 * This method simply returns the object pointed to by the head (front) of 248 * the list. 249 */ 250 void * sci_abstract_list_front( 251 SCI_ABSTRACT_LIST_T * list_p 252 ); 253 254 255 /** 256 * This method simply returns the object pointed to by the tail (back) of 257 * the list. 258 */ 259 void * sci_abstract_list_back( 260 SCI_ABSTRACT_LIST_T * list_p 261 ); 262 263 264 /** 265 * This method will return FALSE if the list is not empty. 266 */ 267 BOOL sci_abstract_list_is_empty( 268 SCI_ABSTRACT_LIST_T * list_p 269 ); 270 271 272 /** 273 * This method will return the number of elements queued in the list. 274 */ 275 U32 sci_abstract_list_size( 276 SCI_ABSTRACT_LIST_T * list_p 277 ); 278 279 280 /** 281 * This method simply returns the next list element in the list. 282 */ 283 SCI_ABSTRACT_ELEMENT_T * sci_abstract_list_get_next( 284 SCI_ABSTRACT_ELEMENT_T * alElement_p 285 ); 286 287 288 /** 289 * This method simply prints the contents of the list. 290 */ 291 void sci_abstract_list_print( 292 SCI_ABSTRACT_LIST_T * list_p 293 ); 294 295 296 /** 297 * This method will simply search the supplied list for the desired object. 298 * It will return a pointer to the object, if it is found. Otherwise 299 * it will return NULL. 300 */ 301 void * sci_abstract_list_find( 302 SCI_ABSTRACT_LIST_T * list_p, 303 void * obj_p 304 ); 305 306 307 /** 308 * This method will simply remove the element at the back (tail) of the list. 309 * It will return a pointer to the object that was removed or NULL if not 310 * found. 311 */ 312 void * sci_abstract_list_popback( 313 SCI_ABSTRACT_LIST_T * list_p 314 ); 315 316 317 /** 318 * This method simply removes the list element at the head of the list 319 * and returns the pointer to the object that was removed. 320 */ 321 void * sci_abstract_list_popfront( 322 SCI_ABSTRACT_LIST_T * list_p 323 ); 324 325 326 327 /** 328 * This method will erase (remove) all instances of the supplied object from 329 * anywhere in the list. 330 */ 331 void sci_abstract_list_erase( 332 SCI_ABSTRACT_LIST_T * list_p, 333 void * obj_p 334 ); 335 336 337 /** 338 * This method simply adds a LIST_ELEMENT for the supplied object to the back 339 * (tail) of the supplied list. 340 */ 341 void sci_abstract_list_pushback( 342 SCI_ABSTRACT_LIST_T * list_p, 343 void * obj_p 344 ); 345 346 347 348 /** 349 * This method simply adds a LIST_ELEMENT for the supplied object to the front 350 * (head) of the supplied list. 351 */ 352 void sci_abstract_list_pushfront( 353 SCI_ABSTRACT_LIST_T * list_p, 354 void * obj_p 355 ); 356 357 358 /** 359 * This method will add the objToAdd_p object to the list before the obj_p. 360 * NOTE: UNIMPLEMENTED 361 */ 362 void sci_abstract_list_insert( 363 SCI_ABSTRACT_LIST_T * list_p, 364 void * obj_p, 365 void * objToAdd_p 366 ); 367 368 369 /** 370 * This method simply frees all the items from the list. 371 */ 372 void sci_abstract_list_clear( 373 SCI_ABSTRACT_LIST_T * list_p 374 ); 375 376 377 /** 378 * This method simply returns the object being pointed to by the list element 379 * (The item being listed). 380 */ 381 void * sci_abstract_list_get_object( 382 SCI_ABSTRACT_ELEMENT_T * alElement_p 383 ); 384 385 386 /** 387 * This method is simply a wrapper to provide the number of elements in 388 * the free list. 389 */ 390 U32 sci_abstract_list_freeList_size( 391 SCI_ABSTRACT_LIST_T * freeList 392 ); 393 394 395 //****************************************************************************** 396 //* 397 //* P R I V A T E M E T H O D S 398 //* 399 //****************************************************************************** 400 401 /** 402 * This method simply performs the common portion of pushing a list element 403 * onto a list. 404 * 405 * WARNING: This is a private helper method that should not be called directly 406 * by any users. 407 */ 408 void private_push_front( 409 SCI_ABSTRACT_ELEMENT_LIST_T * privateList_p, 410 SCI_ABSTRACT_ELEMENT_T * alElement_p 411 ); 412 413 414 /** 415 * This method simply performs the common portion of popping a list element 416 * from a list. 417 * 418 * WARNING: This is a private helper method that should not be called directly 419 * by any users. 420 */ 421 SCI_ABSTRACT_ELEMENT_T * private_pop_front( 422 SCI_ABSTRACT_ELEMENT_LIST_T * privateList_p 423 ); 424 425 426 /** 427 * This method will simply search the supplied list for the desired object. 428 * It will return a pointer to the abstract_list_element if found, otherwise 429 * it will return NULL. 430 */ 431 SCI_ABSTRACT_ELEMENT_T * private_find( 432 SCI_ABSTRACT_ELEMENT_LIST_T * list_p, 433 void * obj_p 434 ); 435 436 437 /** 438 * This private method will free the supplied list element back to the pool 439 * of free list elements. 440 */ 441 void private_pool_free( 442 SCI_ABSTRACT_ELEMENT_POOL_T * free_pool, 443 SCI_ABSTRACT_ELEMENT_T * alElement_p 444 ); 445 446 447 /** 448 * This private method will allocate a list element from the pool of free 449 * list elements. 450 */ 451 SCI_ABSTRACT_ELEMENT_T * private_pool_allocate( 452 SCI_ABSTRACT_ELEMENT_POOL_T * free_pool 453 ); 454 455 456 #else 457 458 //****************************************************************************** 459 //* 460 //* P U B L I C M E T H O D S 461 //* 462 //****************************************************************************** 463 464 /** 465 * Simply return the front element pointer of the list. This returns an element 466 * element as opposed to what the element is pointing to. 467 */ 468 #define sci_abstract_list_get_front( \ 469 list_p \ 470 ) \ 471 ((list_p)->elements.front_p) 472 473 /** 474 * This method simply returns the object pointed to by the head (front) of 475 * the list. 476 */ 477 #define sci_abstract_list_front( \ 478 list_p \ 479 ) \ 480 ( ( (list_p)->elements.front_p ) ? ((list_p)->elements.front_p->object_p) : NULL ) 481 482 /** 483 * This method simply returns the object pointed to by the tail (back) of 484 * the list. 485 */ 486 #define sci_abstract_list_back( \ 487 list_p \ 488 ) \ 489 ( ( (list_p)->elements.back_p ) ? ((list_p)->elements.back_p->object_p) : NULL ) 490 491 /** 492 * This method will return FALSE if the list is not empty. 493 */ 494 #define sci_abstract_list_is_empty( \ 495 list_p \ 496 ) \ 497 ( (list_p)->elements.front_p == NULL ) 498 499 /** 500 * This method will return the number of elements queued in the list. 501 */ 502 #define sci_abstract_list_size( \ 503 list_p \ 504 ) \ 505 ( (list_p)->elements.size ) 506 507 /** 508 * This method simply returns the next list element in the list. 509 */ 510 #define sci_abstract_list_get_next( \ 511 alElement_p \ 512 ) \ 513 ( (alElement_p)->next_p ) 514 515 /** 516 * This method simply prints the contents of the list. 517 */ 518 #define sci_abstract_list_print( \ 519 list_p \ 520 ) \ 521 { \ 522 SCI_ABSTRACT_ELEMENT_T * alElement_p = list_p->elements.front_p; \ 523 \ 524 while (alElement_p != NULL) \ 525 { \ 526 /* Check to see if we found the object for which we are searching. */ \ 527 printf("ITEM next_p 0x%x prev_p 0x%x obj_p 0x%x, 0x%x\n", \ 528 alElement_p->next_p, \ 529 alElement_p->previous_p, \ 530 (U32*) (alElement_p->object_p)); \ 531 \ 532 alElement_p = alElement_p->next_p; \ 533 } \ 534 } 535 536 /** 537 * This method will simply search the supplied list for the desired object. 538 * It will return a pointer to the object, if it is found. Otherwise 539 * it will return NULL. 540 */ 541 #define sci_abstract_list_find( \ 542 list_p, \ 543 obj_p \ 544 ) \ 545 ({ \ 546 sci_abstract_list_get_object(private_find(&(list_p)->elements, (obj_p))); \ 547 }) 548 549 /** 550 * This method will simply remove the element at the back (tail) of the list. 551 * It will return a pointer to the object that was removed or NULL if not 552 * found. 553 */ 554 #define sci_abstract_list_popback( \ 555 list_p \ 556 ) \ 557 ({ \ 558 SCI_ABSTRACT_ELEMENT_LIST_T * elem_list = &(list_p)->elements; \ 559 SCI_ABSTRACT_ELEMENT_T * alElement_p = elem_list->back_p; \ 560 void * obj_p = NULL; \ 561 \ 562 if (alElement_p != NULL) \ 563 { \ 564 obj_p = alElement_p->object_p; \ 565 if (elem_list->back_p == elem_list->front_p) \ 566 { \ 567 elem_list->back_p = elem_list->front_p = NULL; \ 568 } \ 569 else \ 570 { \ 571 elem_list->back_p = elem_list->back_p->previous_p; \ 572 elem_list->back_p->next_p = NULL; \ 573 } \ 574 \ 575 elem_list->size--; \ 576 private_pool_free((list_p)->free_pool, alElement_p); \ 577 } \ 578 \ 579 obj_p; \ 580 }) 581 582 /** 583 * This method simply removes the list element at the head of the list 584 * and returns the pointer to the object that was removed. 585 */ 586 #define sci_abstract_list_popfront( \ 587 list_p \ 588 ) \ 589 ({ \ 590 SCI_ABSTRACT_ELEMENT_T * alElement_p = \ 591 private_pop_front(&(list_p)->elements); \ 592 void * obj_p = NULL; \ 593 \ 594 if (alElement_p != NULL) \ 595 { \ 596 obj_p = alElement_p->object_p; \ 597 private_pool_free((list_p)->free_pool, alElement_p); \ 598 } \ 599 \ 600 obj_p; \ 601 }) 602 603 /** 604 * This method will erase (remove) all instances of the supplied object from 605 * anywhere in the list. 606 */ 607 #define sci_abstract_list_erase( \ 608 list_p, \ 609 obj_p \ 610 ) \ 611 { \ 612 SCI_ABSTRACT_ELEMENT_LIST_T * elem_list = &(list_p)->elements; \ 613 SCI_ABSTRACT_ELEMENT_T * alElement_p; \ 614 \ 615 while ((alElement_p = private_find(elem_list, (obj_p))) != NULL) \ 616 { \ 617 if (alElement_p == elem_list->front_p) \ 618 { \ 619 sci_abstract_list_popfront(list_p); \ 620 } \ 621 else if (alElement_p == elem_list->back_p) \ 622 { \ 623 sci_abstract_list_popback(list_p); \ 624 } \ 625 else \ 626 { \ 627 alElement_p->previous_p->next_p = alElement_p->next_p; \ 628 alElement_p->next_p->previous_p = alElement_p->previous_p; \ 629 elem_list->size--; \ 630 private_pool_free((list_p)->free_pool, alElement_p); \ 631 } \ 632 } \ 633 } 634 635 /** 636 * This method simply adds a LIST_ELEMENT for the supplied object to the back 637 * (tail) of the supplied list. 638 */ 639 #define sci_abstract_list_pushback( \ 640 list_p, \ 641 obj_p \ 642 ) \ 643 { \ 644 SCI_ABSTRACT_ELEMENT_LIST_T * elem_list = &(list_p)->elements; \ 645 SCI_ABSTRACT_ELEMENT_T * alElement_p \ 646 = private_pool_allocate((list_p)->free_pool); \ 647 assert(alElement_p != NULL); \ 648 \ 649 alElement_p->object_p = (obj_p); \ 650 \ 651 if (elem_list->front_p == NULL) \ 652 { \ 653 elem_list->front_p = elem_list->back_p = alElement_p; \ 654 } \ 655 else \ 656 { \ 657 elem_list->back_p->next_p = alElement_p; \ 658 alElement_p->previous_p = elem_list->back_p; \ 659 elem_list->back_p = alElement_p; \ 660 } \ 661 \ 662 elem_list->size++; \ 663 } 664 665 /** 666 * This method simply adds a LIST_ELEMENT for the supplied object to the front 667 * (head) of the supplied list. 668 */ 669 #define sci_abstract_list_pushfront( \ 670 list_p, \ 671 obj_p \ 672 ) \ 673 { \ 674 SCI_ABSTRACT_ELEMENT_T * alElement_p = \ 675 private_pool_allocate((list_p)->free_pool); \ 676 alElement_p->object_p = (obj_p); \ 677 private_push_front(&(list_p)->elements, alElement_p); \ 678 } 679 680 /** 681 * This method will add the objToAdd_p object to the list before the obj_p. 682 * NOTE: UNIMPLEMENTED 683 */ 684 #define sci_abstract_list_insert( \ 685 list_p, \ 686 obj_p, \ 687 objToAdd_p \ 688 ) \ 689 { \ 690 SCI_ABSTRACT_ELEMENT_LIST_T * elem_list = &(list_p)->elements; \ 691 \ 692 SCI_ABSTRACT_ELEMENT_T * obj_element = private_find(elem_list, obj_p); \ 693 \ 694 SCI_ABSTRACT_ELEMENT_T * objToAdd_element = \ 695 private_pool_allocate((list_p)->free_pool); \ 696 \ 697 objToAdd_element->object_p = objToAdd_p; \ 698 \ 699 ASSERT(obj_element != NULL); \ 700 ASSERT(objToAdd_element != NULL); \ 701 \ 702 if (obj_element == elem_list->front_p) \ 703 { \ 704 objToAdd_element->object_p = (objToAdd_p); \ 705 private_push_front(&(list_p)->elements, objToAdd_element); \ 706 } \ 707 else \ 708 { \ 709 obj_element->previous_p->next_p = objToAdd_element; \ 710 objToAdd_element->previous_p = obj_element->previous_p; \ 711 \ 712 obj_element->previous_p = objToAdd_element; \ 713 objToAdd_element->next_p = obj_element; \ 714 \ 715 elem_list->size++; \ 716 } \ 717 } 718 719 /** 720 * This method simply frees all the items from the list. 721 */ 722 #define sci_abstract_list_clear( \ 723 list_p \ 724 ) \ 725 { \ 726 while ((list_p)->elements.size > 0) \ 727 sci_abstract_list_popfront((list_p)); \ 728 } 729 730 /** 731 * This method simply returns the object being pointed to by the list element 732 * (The item being listed). 733 */ 734 #define sci_abstract_list_get_object( \ 735 alElement_p \ 736 ) \ 737 ({ \ 738 void * obj_p = NULL; \ 739 if ((alElement_p) != NULL) \ 740 obj_p = (alElement_p)->object_p; \ 741 \ 742 obj_p; \ 743 }) 744 745 /** 746 * This method is simply a wrapper to provide the number of elements in 747 * the free list. 748 */ 749 #define sci_abstract_list_freeList_size(freeList) (sci_abstract_list_size(freeList)) 750 751 //****************************************************************************** 752 //* 753 //* P R I V A T E M E T H O D S 754 //* 755 //****************************************************************************** 756 757 /** 758 * This method simply performs the common portion of pushing a list element 759 * onto a list. 760 * 761 * WARNING: This is a private helper method that should not be called directly 762 * by any users. 763 */ 764 #define private_push_front( \ 765 privateList_p, \ 766 alElement_p \ 767 ) \ 768 { \ 769 if ((privateList_p)->front_p == NULL) \ 770 { \ 771 (privateList_p)->front_p = (privateList_p)->back_p = (alElement_p); \ 772 (alElement_p)->next_p = (alElement_p)->previous_p = NULL; \ 773 } \ 774 else \ 775 { \ 776 (alElement_p)->next_p = (privateList_p)->front_p; \ 777 (alElement_p)->previous_p = NULL; \ 778 (privateList_p)->front_p->previous_p = (alElement_p); \ 779 (privateList_p)->front_p = (alElement_p); \ 780 } \ 781 \ 782 (privateList_p)->size++; \ 783 } 784 785 /** 786 * This method simply performs the common portion of popping a list element 787 * from a list. 788 * 789 * WARNING: This is a private helper method that should not be called directly 790 * by any users. 791 */ 792 #define private_pop_front( \ 793 privateList_p \ 794 ) \ 795 ({ \ 796 SCI_ABSTRACT_ELEMENT_T * alElement_p = (privateList_p)->front_p; \ 797 \ 798 if (alElement_p != NULL) \ 799 { \ 800 if ((privateList_p)->front_p == (privateList_p)->back_p) \ 801 { \ 802 (privateList_p)->front_p = (privateList_p)->back_p = NULL; \ 803 } \ 804 else \ 805 { \ 806 (privateList_p)->front_p = (privateList_p)->front_p->next_p; \ 807 (privateList_p)->front_p->previous_p = NULL; \ 808 } \ 809 \ 810 (privateList_p)->size--; \ 811 } \ 812 \ 813 alElement_p; \ 814 }) 815 816 /** 817 * This method will simply search the supplied list for the desired object. 818 * It will return a pointer to the abstract_list_element if found, otherwise 819 * it will return NULL. 820 */ 821 #define private_find( \ 822 list_p, \ 823 obj_p \ 824 ) \ 825 ({ \ 826 SCI_ABSTRACT_ELEMENT_T * alElement_p = (list_p)->front_p; \ 827 \ 828 while (alElement_p != NULL) \ 829 { \ 830 /* Check to see if we found the object for which we are searching. */ \ 831 if (alElement_p->object_p == (void*) (obj_p)) \ 832 { \ 833 break; \ 834 } \ 835 \ 836 alElement_p = alElement_p->next_p; \ 837 } \ 838 \ 839 alElement_p; \ 840 }) 841 842 /** 843 * This private method will free the supplied list element back to the pool 844 * of free list elements. 845 */ 846 #define private_pool_free( \ 847 free_pool, \ 848 alElement_p \ 849 ) \ 850 { \ 851 /* Push the list element back to the head to get better locality of */ \ 852 /* reference with the cache. */ \ 853 private_push_front(&(free_pool)->free_list, (alElement_p)); \ 854 } 855 856 /** 857 * This private method will allocate a list element from the pool of free 858 * list elements. 859 */ 860 #define private_pool_allocate(free_pool) \ 861 ({ \ 862 SCI_ABSTRACT_ELEMENT_T * alElement_p; \ 863 \ 864 alElement_p = private_pop_front(&(free_pool)->free_list); \ 865 \ 866 memset(alElement_p, 0, sizeof(SCI_ABSTRACT_ELEMENT_T)); \ 867 alElement_p; \ 868 }) 869 870 #endif 871 #endif // _ABSTRACT_LIST_H_ 872