list.c

Go to the documentation of this file.
00001 /*                          L I S T . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 2004-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** \addtogroup bu_list */
00023 /*@{*/
00024 /** @file ./libbu/list.c
00025  *
00026  * @brief Support routines for linked lists.
00027  *
00028  *  Generic bu_list routines.
00029  *
00030  *  @author     Michael John Muuss
00031  *  @author     Lee A. Butler
00032  *
00033  *  @par Source -
00034  *  @n  The U. S. Army Research Laboratory
00035  *  @n  Aberdeen Proving Ground, Maryland  21005-5068  USA
00036  */
00037 
00038 #ifndef lint
00039 static const char libbu_list_RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/libbu/list.c,v 14.11 2006/09/03 15:14:07 lbutler Exp $ (ARL)";
00040 #endif
00041 
00042 #include "common.h"
00043 
00044 
00045 #include <stdio.h>
00046 #include "machine.h"
00047 #include "bu.h"
00048 
00049 #include <assert.h>
00050 
00051 /**
00052  *                      B U _ L I S T _ N E W
00053  *
00054  *      Creates and initializes a bu_list head structure
00055  */
00056 struct bu_list *
00057 bu_list_new(void)
00058 {
00059         struct bu_list *new;
00060 
00061         BU_GETSTRUCT( new, bu_list );
00062         BU_LIST_INIT( new );
00063 
00064         return( new );
00065 }
00066 
00067 /**
00068  *                      B U _ L I S T _ P O P
00069  *
00070  *      Returns the results of BU_LIST_POP
00071  */
00072 struct bu_list *
00073 bu_list_pop( struct bu_list *hp )
00074 {
00075         struct bu_list *p;
00076 
00077         BU_LIST_POP( bu_list, hp, p );
00078 
00079         return( p );
00080 }
00081 
00082 /**
00083  *                      B U _ L I S T _ L E N
00084  *
00085  *  Returns the number of elements on a bu_list brand linked list.
00086  */
00087 int
00088 bu_list_len(register const struct bu_list *hd)
00089 {
00090         register int                    count = 0;
00091         register const struct bu_list   *ep;
00092 
00093         for( BU_LIST_FOR( ep, bu_list, hd ) )  {
00094                 count++;
00095         }
00096         return count;
00097 }
00098 
00099 /**
00100  *                      B U _ L I S T _ R E V E R S E
00101  *
00102  *      Reverses the order of elements in a bu_list linked list.
00103  */
00104 void
00105 bu_list_reverse(register struct bu_list *hd)
00106 {
00107         struct bu_list tmp_hd;
00108         register struct bu_list *ep;
00109 
00110         BU_CK_LIST_HEAD( hd );
00111 
00112         BU_LIST_INIT( &tmp_hd );
00113         BU_LIST_INSERT_LIST( &tmp_hd, hd );
00114 
00115         while( BU_LIST_WHILE( ep, bu_list, &tmp_hd ) )  {
00116                 BU_LIST_DEQUEUE( ep );
00117                 BU_LIST_APPEND( hd, ep );
00118         }
00119 }
00120 
00121 /**
00122  *                      B U _ L I S T _ F R E E
00123  *
00124  *  Given a list of structures allocated with bu_malloc() enrolled
00125  *  on a bu_list head, walk the list and free the structures.
00126  *  This routine can only be used when the structures have no interior
00127  *  pointers.
00128  */
00129 void
00130 bu_list_free(struct bu_list *hd)
00131 {
00132         struct bu_list  *p;
00133 
00134         while( BU_LIST_WHILE( p, bu_list, hd ) )  {
00135                 BU_LIST_DEQUEUE( p );
00136                 bu_free( (genptr_t)p, "struct bu_list" );
00137         }
00138 }
00139 
00140 /**
00141  *                      B U _ L I S T _ P A R A L L E L _ A P P E N D
00142  *
00143  *  Simple parallel-safe routine for appending a data structure to the end
00144  *  of a bu_list doubly-linked list.
00145  *  @par Issues:
00146  *      Only one semaphore shared by all list heads.
00147  *  @n  No portable way to notify waiting thread(s) that are sleeping
00148  */
00149 void
00150 bu_list_parallel_append(struct bu_list *headp, struct bu_list *itemp)
00151 {
00152         bu_semaphore_acquire(BU_SEM_LISTS);
00153         BU_LIST_INSERT( headp, itemp );         /* insert before head = append */
00154         bu_semaphore_release(BU_SEM_LISTS);
00155 }
00156 
00157 /**
00158  *                      B U _ L I S T _ P A R A L L E L _ D E Q U E U E
00159  *
00160  *  Simple parallel-safe routine for dequeueing one data structure from
00161  *  the head of a bu_list doubly-linked list.
00162  *  If the list is empty, wait until some other thread puts something on
00163  *  the list.
00164  *
00165  *  @par Issues:
00166  *      No portable way to not spin and burn CPU time while waiting
00167  *  @n  for something to show up on the list.
00168  */
00169 struct bu_list *
00170 bu_list_parallel_dequeue(struct bu_list *headp)
00171 {
00172         for(;;)  {
00173                 register struct bu_list *p;
00174 
00175                 bu_semaphore_acquire(BU_SEM_LISTS);
00176                 p = BU_LIST_FIRST(bu_list, headp);
00177                 if( BU_LIST_NOT_HEAD( p, headp ) )  {
00178                         BU_LIST_DEQUEUE(p);
00179                         bu_semaphore_release(BU_SEM_LISTS);
00180                         return p;
00181                 }
00182                 bu_semaphore_release(BU_SEM_LISTS);
00183 
00184                 /* List is empty, wait a moment and peek again */
00185 #if (defined(sgi) && defined(mips)) || (defined(__sgi) && defined(__mips))
00186                 sginap(1);
00187 #endif
00188         }
00189         /* NOTREACHED */
00190 }
00191 
00192 /**
00193  *                      B U _ C K _ L I S T
00194  *
00195  *  Generic bu_list doubly-linked list checker.
00196  */
00197 void
00198 bu_ck_list(const struct bu_list *hd, const char *str)
00199 {
00200         register const struct bu_list   *cur;
00201         int     head_count = 0;
00202 
00203         cur = hd;
00204         do  {
00205                 if( cur->magic == BU_LIST_HEAD_MAGIC )  head_count++;
00206                 if( !cur->forw )  {
00207                         bu_log("bu_ck_list(%s) cur=x%x, cur->forw=x%x, hd=x%x\n",
00208                                 str, cur, cur->forw, hd );
00209                         bu_bomb("bu_ck_list() forw\n");
00210                 }
00211                 if( cur->forw->back != cur )  {
00212                         bu_log("bu_ck_list(%s) cur=x%x, cur->forw=x%x, cur->forw->back=x%x, hd=x%x\n",
00213                                 str, cur, cur->forw, cur->forw->back, hd );
00214                         bu_bomb("bu_ck_list() forw->back\n");
00215                 }
00216                 if( !cur->back )  {
00217                         bu_log("bu_ck_list(%s) cur=x%x, cur->back=x%x, hd=x%x\n",
00218                                 str, cur, cur->back, hd );
00219                         bu_bomb("bu_ck_list() back\n");
00220                 }
00221                 if( cur->back->forw != cur )  {
00222                         bu_log("bu_ck_list(%s) cur=x%x, cur->back=x%x, cur->back->forw=x%x, hd=x%x\n",
00223                                 str, cur, cur->back, cur->back->forw, hd );
00224                         bu_bomb("bu_ck_list() back->forw\n");
00225                 }
00226                 cur = cur->forw;
00227         } while( cur != hd );
00228 
00229         if( head_count != 1 )  {
00230                 bu_log("bu_ck_list(%s) head_count = %d, hd=x%x\n", str, head_count, hd);
00231                 bu_bomb("bu_ck_list() headless!\n");
00232         }
00233 }
00234 
00235 /**
00236  *                      B U _ C K _ L I S T _ M A G I C
00237  *
00238  *  bu_list doubly-linked list checker which checks the magic number for
00239  *      all elements in the linked list
00240  */
00241 void
00242 bu_ck_list_magic(const struct bu_list *hd, const char *str, const long int magic)
00243 {
00244         register const struct bu_list   *cur;
00245         int     head_count = 0;
00246         int     item = 0;
00247 
00248         cur = hd;
00249         do  {
00250                 if( cur->magic == BU_LIST_HEAD_MAGIC )  {
00251                         head_count++;
00252                 } else if( cur->magic != magic ) {
00253                         bu_log("bu_ck_list(%s) cur magic=(%s)x%x, cur->forw magic=(%s)x%x, hd magic=(%s)x%x, item=%d\n",
00254                                 str, bu_identify_magic(cur->magic), cur->magic,
00255                                 bu_identify_magic(cur->forw->magic), cur->forw->magic,
00256                                 bu_identify_magic(hd->magic), hd->magic,
00257                                 item);
00258                         bu_bomb("bu_ck_list_magic() cur->magic\n");
00259                 }
00260 
00261                 if( !cur->forw )  {
00262                         bu_log("bu_ck_list_magic(%s) cur=x%x, cur->forw=x%x, hd=x%x, item=%d\n",
00263                                 str, cur, cur->forw, hd, item );
00264                         bu_bomb("bu_ck_list_magic() forw NULL\n");
00265                 }
00266                 if( cur->forw->back != cur )  {
00267                         bu_log("bu_ck_list_magic(%s) cur=x%x, cur->forw=x%x, cur->forw->back=x%x, hd=x%x, item=%d\n",
00268                                 str, cur, cur->forw, cur->forw->back, hd, item );
00269                         bu_log(" cur=%s, cur->forw=%s, cur->forw->back=%s\n",
00270                                 bu_identify_magic(cur->magic),
00271                                 bu_identify_magic(cur->forw->magic),
00272                                 bu_identify_magic(cur->forw->back->magic) );
00273                         bu_bomb("bu_ck_list_magic() cur->forw->back != cur\n");
00274                 }
00275                 if( !cur->back )  {
00276                         bu_log("bu_ck_list_magic(%s) cur=x%x, cur->back=x%x, hd=x%x, item=%d\n",
00277                                 str, cur, cur->back, hd, item );
00278                         bu_bomb("bu_ck_list_magic() back NULL\n");
00279                 }
00280                 if( cur->back->forw != cur )  {
00281                         bu_log("bu_ck_list_magic(%s) cur=x%x, cur->back=x%x, cur->back->forw=x%x, hd=x%x, item=%d\n",
00282                                 str, cur, cur->back, cur->back->forw, hd, item );
00283                         bu_bomb("bu_ck_list_magic() cur->back->forw != cur\n");
00284                 }
00285                 cur = cur->forw;
00286                 item++;
00287         } while( cur != hd );
00288 
00289         if( head_count != 1 )  {
00290                 bu_log("bu_ck_list_magic(%s) head_count = %d, hd=x%x, items=%d\n", str, head_count, hd, item);
00291                 bu_bomb("bu_ck_list_magic() headless!\n");
00292         }
00293 }
00294 
00295 /* XXX - apparently needed by muves */
00296 struct bu_list *
00297 bu_list_dequeue_next( struct bu_list *hp, struct bu_list *p )
00298 {
00299         struct bu_list *p2;
00300 
00301         hp = hp;
00302         p2 = BU_LIST_NEXT( bu_list, p );
00303         BU_LIST_DEQUEUE( p2 );
00304 
00305         return( p2 );
00306 }
00307 
00308 /*@}*/
00309 
00310 /*
00311  * Local Variables:
00312  * mode: C
00313  * tab-width: 8
00314  * c-basic-offset: 4
00315  * indent-tabs-mode: t
00316  * End:
00317  * ex: shiftwidth=4 tabstop=8
00318  */

Generated on Mon Sep 18 01:24:48 2006 for BRL-CAD by  doxygen 1.4.6