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