sci_abstract_list.h revision 330897
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: stable/11/sys/dev/isci/scil/sci_abstract_list.h 330897 2018-03-14 03:19:51Z eadler $ 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 */ 113typedef 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 */ 139typedef 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 */ 168typedef 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 */ 198typedef 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 219void 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 225void 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 */ 243SCI_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 */ 252void * 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 */ 261void * 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 */ 269BOOL 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 */ 277U32 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 */ 285SCI_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 */ 293void 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 */ 303void * 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 */ 314void * 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 */ 323void * 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 */ 333void 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 */ 343void 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 */ 354void 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 */ 364void 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 */ 374void 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 */ 383void * 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 */ 392U32 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 */ 410void 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 */ 423SCI_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 */ 433SCI_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 */ 443void 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 */ 453SCI_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