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