[ccan] [PATCH] list: add list_for_each_rev_safe
Rusty Russell
rusty at rustcorp.com.au
Mon Mar 30 16:32:29 AEDT 2015
David Gibson <david at gibson.dropbear.id.au> writes:
> On Sun, Oct 05, 2014 at 12:20:45PM +0000, Eric Wong wrote:
>> Deleting while iterating backwards will be needed in the
>> Ruby st_foreach_reverse_check implementation if we decide
>> to port Ruby's st.c to use ccan/list.
>>
>> ref: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/65408
>>
>> Signed-off-by: Eric Wong <normalperson at yhbt.net>
>> ---
>> ccan/list/list.h | 27 ++++++++++++++++++++++++++-
>> ccan/list/test/run.c | 31 ++++++++++++++++++++++++++++++-
>> 2 files changed, 56 insertions(+), 2 deletions(-)
>>
>> diff --git a/ccan/list/list.h b/ccan/list/list.h
>> index 983675b..b4a6cdf 100644
>> --- a/ccan/list/list.h
>> +++ b/ccan/list/list.h
>> @@ -527,6 +527,32 @@ static inline const void *list_tail_(const struct list_head *h, size_t off)
>> i = container_of_var(i->member.prev, i, member))
>>
>> /**
>> + * list_for_each_rev_safe - iterate through a list backwards,
>> + * maybe during deletion
>> + * @h: the list_head
>> + * @i: the structure containing the list_node
>> + * @nxt: the structure containing the list_node
>> + * @member: the list_node member of the structure
>> + *
>> + * This is a convenient wrapper to iterate @i over the entire list backwards.
>> + * It's a for loop, so you can break and continue as normal. The extra
>> + * variable * @nxt is used to hold the next element, so you can delete @i
>> + * from the list.
>> + *
>> + * Example:
>> + * struct child *next;
>> + * list_for_each_rev_safe(&parent->children, child, next, list) {
>> + * printf("Name: %s\n", child->name);
>> + * }
>> + */
>> +#define list_for_each_rev_safe(h, i, nxt, member) \
>> + for (i = container_of_var(list_debug(h, LIST_LOC)->n.prev, i, member), \
>> + nxt = container_of_var(i->member.prev, i, member); \
>> + &i->member != &(h)->n; \
>> + i = nxt, \
>> + nxt = container_of_var(i->member.prev, i, member))
>
>
> For proper orthogonality, I think rather than implementing it this
> way, you should implement list_for_each_rev_safe_off() and implement
> list_for_each_rev_safe() in terms of it, like the forwards
> list_for_each_safe().
>
> Also, I think the way that's implemented is to avoid double-evaluation
> of macro arguments, so it's possible there's such a double evaluation
> in your version.
Well, it matches list_for_each_rev().
I don't use the offset versions, so I'm happy to leave it to someone who
does to fix it.
And both variants will multi-evaluate h, so there's no win there.
Thanks!
Rusty.
More information about the ccan
mailing list