Here is a cyclic list traversal macro, which is alleged to meet the following requirements:
NULL
, it scans the
full list, starting at the beginning.
Here is one solution that meets these requirements:
1 #define list_next_element(p, h, t, m) \ 2 (p)->next != h \ 3 ? list_entry((p)->next, t, m) \ 4 : list_entry((h)->next, t, m) 5 #define list_for_each_entry_proceed(t, tt, h, m) \ 6 for ((t) = (t) == NULL \ 7 ? list_next_element((h), (h), typeof(*(t)), m) \ 8 : list_next_element(&(t)->m, (h), typeof(*(t)), m), \ 9 (tt) = NULL; \ 10 (t) != (tt) && (h)->next != (h); \ 11 (tt) = ((tt) == NULL ? (t) : (tt)), \ 12 (t) = list_next_element(&(t)->m, (h), typeof(*t), m))
The list_next_element()
helper macro is on lines 1-4.
It differs from the Linux kernel's list_next_entry()
in that it skips the header.
Of course, given an empty list, it will yield a pointer to the
mythical element containing the header, and the caller must deal
with this possibility.
The list_for_each_entry_proceed()
macro is shown on
lines 5-12.
It is a big “for” statement, with each part described
by a paragraph below.
First, the initialization part on lines 6-9.
If t
is initially NULL
, then
line 7 points it to the first entry in the list,
otherwise line 8 points it to the successor of the entry
referenced by the initial value of t
.
Note that if the list is empty, the new value of t
will
reference the mythical entry containing the header.
In either case, line 9 sets the value of tt
to
NULL
.
The check part on line 10 is straightforward: we stop if we have arrived at the first entry processed or if the list is empty.
The increment part on lines 11 and 12 is more subtle.
Line 11 sets tt
to t
, but only if
tt
is NULL
.
This captures the first entry, which is used to check for loop termination.
Line 12 uses list_next_element()
to advance to the
next list entry, excluding the mythical entry enclosing the header.
Note that empty lists do not get this far due to the check on Line 10.
Creating a version that is safe for RCU readers is left as an exercise for the reader. ;–)