All of lore.kernel.org
 help / color / mirror / Atom feed
From: vincent guffens <v.guffens@imperial.ac.uk>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: Re: RE : a simple list
Date: Tue, 09 May 2006 10:08:24 +0100	[thread overview]
Message-ID: <44605C08.3020100@imperial.ac.uk> (raw)
In-Reply-To: <003001c672fa$5adab170$0b00a8c0@yoda>

Thank you for this information. Adding the concept of context is indeed
the right idea. I was doing it as follows

void function (grub_device_t dev)
{
 grub_device_t it;
 auto int look_for_dev (grub_device_t);

  int look_for_dev (grub_device_t grub_device_t other_dev)
  {
     return compare (dev, other_dev)
  }

grub_iterate_list_brk (grub_devices, look_for_dev, it);
}

but it has to be compared with something like

void function (grub_device_t dev)
{
  grub_device_t it = grub_devices;

  while (it)
  {
     if ( compare (dev, it) )
       break;
  }
}


which is obviously simpler. Maybe the only two functions that are really
needed are add and del ?

Also, I found out yesterday that
the compiler throws out warning about strict aliasing when using the
iterate function. I had to add -fno-strict-aliasing to get rid of them.



Eric Salomé wrote:
> Hi,
> 
> I didn’t take a good look at current iterate functions in Grub 2, yet.
> 
>  
> 
> Most iterations needs a “init” (before treatment of first item) and a
> “fini” (after treatment of last item).
> 
> Further more, one might want to make iteration functions “re-entrant”
> (or recursive), or call-back other functions in a generic way.
> 
>  
> 
> One way to get to such behavior easily cost a bit more than the example
> you provided : 
> 
> you may just add an argument (let’s call it the context object) to the
> call of the iterate function :
> 
>  
> 
> #define grub_iterate_list(list, func, context) \
>   {typeof(list) el = list; while (el) {func(context, el); el=el->next;}
> func(context, NULL)}
> or
> 
> #define grub_iterate_list(list, func) \
>   {void * context = NULL; typeof(list) el = list; while (el)
> {func(&context, el); el=el->next;} func(&context, NULL)}
> but I prefer the first define as it allows transmission of a full
> context to the iteration function.
> 
>  
> 
> my_struct * my_ctxt;
> 
>  
> 
> my_ctxt = NULL; grub_iterate_list(list, my_func, &my_ctxt);
> 
>  
> 
> void my_func (my_struct ** ctxt, my_item * item) {
> 
>       if (item == NULL) {
> 
>           /* End of iteration : Do any cleanup */
> 
>           if (*ctxt == NULL) return;
> 
>           free (*ctxt) ……
> 
>           …..
> 
>           return;
> 
>       }
> 
>       if (*ctxt == NULL) {
> 
>            /* First iteration : Do any initialization */
> 
>            *ctxt = malloc (sizeof (my_struct)); ….
> 
>            …..
> 
> }
> 
> /* Do the iteration stuff */
> 
> …..
> 
> return;
> 
> }
> 
>  
> 
> In grub_iterate_list_brk, you can use context to send a patern or model
> object to compare each item of the list with.
> 
>  
> 
> The draw back is it makes iteration function a bit less readable, but a
> lot more powerful.
> 
>                         
> 
> _________________________________________
> 
> Eric Salomé – Paris, France
> 
>  
> 
> -----Message d'origine-----
> De : grub-devel-bounces+esalome=ctx.net@gnu.org
> [mailto:grub-devel-bounces+esalome=ctx.net@gnu.org] De la part de
> Guffens, Vincent
> Envoyé : lundi 8 mai 2006 01:14
> À : grub-devel@gnu.org
> Objet : a simple list
> 
>  
> 
> Hi,
> 
> I need to use a simple list to register the pci devices, drivers and so
> on. I notice that there are lists like that already in the code so what
> would you think about having a list.h file like that ?
> 
> /* A very simple list.
>  *
>  * If you want a list of struct myitem
>  * you do
>  *
>  * struct myitem *item_list;
>  *
>  * where myitem MUST have its next pointer as the FIRST field
>  *
>  * and you can then add, delete the EL item,
>  * grub_add_list (&item_list, el);
>  * grub_del_list (&item_list, el);
>  *
>  * or call HOOK(item) for each element of the list
>  * grub_iterate_list (item_list, hook);
>  *
>  * This brk version will point el to the list item for which
>  * HOOK(EL) returns a non-null value
>  * grub_iterate_list_brk (item_list, hook, el);
>  *
>  */
> 
> struct obj {
>   struct obj *next; /* MUST BE FIRST */
> };
> 
> #define grub_del_list(list, el) _grub_del_list((struct obj**) list,
> (struct obj*) el)
> #define grub_add_list(list, el) _grub_add_list((struct obj**) list,
> (struct obj*) el)
> #define grub_find_list(list, el) \
>   (typeof(list)) _grub_find_list((struct obj*) list, (struct obj*) el)
> #define grub_iterate_list(list, func) \
>   {typeof(list) el = list; while (el) {func(el); el=el->next;}}
> #define grub_iterate_list_brk(list, func, it) \
>   {typeof(list) el = list; it = 0; \
>     while (el) {if (func(el)) {it = el; break;} el=el->next; }}
> 
> static inline struct obj*  _grub_find_list (struct obj *list, struct obj
> *el)
> {
>   struct obj *it = list;
>   for (it = list; it; it=it->next)
>   {
>     if (it == el) return el;
>   }
>   return 0;
> };
> 
> static inline void _grub_add_list (struct obj **list, struct obj *el)
> {
>   if ( (!el) || (_grub_find_list (*list, el)) )
>     return;
>  
>   el->next = *list;
>   *list = el;
> };
> 
> static inline void _grub_del_list (struct obj **list, struct obj *el)
> {
>   struct obj **p;
>   struct obj *q;
> 
>   for (p = list, q = *p; q; p = &(q->next), q = q->next)
>     if (q == el)
>       {
>         *p = q->next;
>         break;
>       }
> };
> 
> 
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel


-- 
		Vincent Guffens
		Intelligent Systems & Networks Group
		Research associate, Imperial College



  reply	other threads:[~2006-05-09  9:08 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-05-07 23:14 a simple list Guffens, Vincent
2006-05-08 23:51 ` RE : " Eric Salomé
2006-05-09  9:08   ` vincent guffens [this message]
2006-05-09 20:31 ` Eric Salomé
2006-05-09 21:29   ` vincent guffens

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=44605C08.3020100@imperial.ac.uk \
    --to=v.guffens@imperial.ac.uk \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.