xref: /freebsd/sys/dev/isci/scil/sci_abstract_list.h (revision 81ad6265)
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