sci_abstract_list.h revision 331722
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: stable/11/sys/dev/isci/scil/sci_abstract_list.h 331722 2018-03-29 02:50:57Z eadler $
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