[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: RE : a simple list
From: |
vincent guffens |
Subject: |
Re: RE : a simple list |
Date: |
Tue, 09 May 2006 10:08:24 +0100 |
User-agent: |
Debian Thunderbird 1.0.7 (X11/20051017) |
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 : address@hidden
> [mailto:address@hidden De la part de
> Guffens, Vincent
> Envoyé : lundi 8 mai 2006 01:14
> À : address@hidden
> 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
> address@hidden
> http://lists.gnu.org/mailman/listinfo/grub-devel
--
Vincent Guffens
Intelligent Systems & Networks Group
Research associate, Imperial College