1/*- 2 * This file is provided under a dual BSD/GPLv2 license. When using or 3 * redistributing this file, you may do so under either license. 4 * 5 * GPL LICENSE SUMMARY 6 * 7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of version 2 of the GNU General Public License as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21 * The full GNU General Public License is included in this distribution 22 * in the file called LICENSE.GPL. 23 * 24 * BSD LICENSE 25 * 26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 33 * * Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * * Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in 37 * the documentation and/or other materials provided with the 38 * distribution. 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 * 52 * $FreeBSD: releng/10.2/sys/dev/isci/scil/sci_abstract_list.h 231136 2012-02-07 17:43:58Z jimharris $ 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 */ 111typedef 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 */ 137typedef 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 */ 166typedef 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 */ 196typedef 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 217void 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 223void 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 */ 241SCI_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 */ 250void * 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 */ 259void * 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 */ 267BOOL 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 */ 275U32 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 */ 283SCI_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 */ 291void 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 */ 301void * 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 */ 312void * 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 */ 321void * 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 */ 331void 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 */ 341void 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 */ 352void 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 */ 362void 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 */ 372void 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 */ 381void * 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 */ 390U32 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 */ 408void 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 */ 421SCI_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 */ 431SCI_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 */ 441void 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 */ 451SCI_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