Message ID | 20190624055253.31183-2-hch@lst.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [01/12] list.h: add a list_pop helper | expand |
On Mon, Jun 24, 2019 at 07:52:42AM +0200, Christoph Hellwig wrote: > We have a very common pattern where we want to delete the first entry > from a list and return it as the properly typed container structure. > > Add a list_pop helper to implement this behavior. > > Signed-off-by: Christoph Hellwig <hch@lst.de> > --- > include/linux/list.h | 22 ++++++++++++++++++++++ > 1 file changed, 22 insertions(+) > > diff --git a/include/linux/list.h b/include/linux/list.h > index e951228db4b2..e07a5f54cc9d 100644 > --- a/include/linux/list.h > +++ b/include/linux/list.h > @@ -500,6 +500,28 @@ static inline void list_splice_tail_init(struct list_head *list, > pos__ != head__ ? list_entry(pos__, type, member) : NULL; \ > }) > > +/** > + * list_pop - delete the first entry from a list and return it > + * @list: the list to take the element from. > + * @type: the type of the struct this is embedded in. > + * @member: the name of the list_head within the struct. > + * > + * Note that if the list is empty, it returns NULL. > + */ > +#define list_pop(list, type, member) \ Unnecessary space after the ')' here, though I can fix that up if I merge this version of the series... Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> --D > +({ \ > + struct list_head *head__ = (list); \ > + struct list_head *pos__ = READ_ONCE(head__->next); \ > + type *entry__ = NULL; \ > + \ > + if (pos__ != head__) { \ > + entry__ = list_entry(pos__, type, member); \ > + list_del(pos__); \ > + } \ > + \ > + entry__; \ > +}) > + > /** > * list_next_entry - get the next element in list > * @pos: the type * to cursor > -- > 2.20.1 >
On Mon, Jun 24, 2019 at 07:52:42AM +0200, Christoph Hellwig wrote: > +/** > + * list_pop - delete the first entry from a list and return it > + * @list: the list to take the element from. > + * @type: the type of the struct this is embedded in. > + * @member: the name of the list_head within the struct. > + * > + * Note that if the list is empty, it returns NULL. > + */ > +#define list_pop(list, type, member) \ The usual convention in list.h is that list_foo uses the list head and list_foo_entry uses the container type. So I think this should be renamed to list_pop_entry() at least. Do we also want: static inline struct list_head *list_pop(struct list_head *head) { struct list_head *first = READ_ONCE(head->next); if (first == head) return NULL; __list_del(head, first->next); return first; } we also seem to prefer using inline functions over #defines in this header file.
On Mon, Jun 24, 2019 at 08:51:37AM -0700, Matthew Wilcox wrote: > The usual convention in list.h is that list_foo uses the list head and > list_foo_entry uses the container type. So I think this should be > renamed to list_pop_entry() at least. Do we also want: > > static inline struct list_head *list_pop(struct list_head *head) > { > struct list_head *first = READ_ONCE(head->next); > > if (first == head) > return NULL; > __list_del(head, first->next); > return first; > } > > we also seem to prefer using inline functions over #defines in this > header file. Sure, I can rename it and split the implementation.
diff --git a/include/linux/list.h b/include/linux/list.h index e951228db4b2..e07a5f54cc9d 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -500,6 +500,28 @@ static inline void list_splice_tail_init(struct list_head *list, pos__ != head__ ? list_entry(pos__, type, member) : NULL; \ }) +/** + * list_pop - delete the first entry from a list and return it + * @list: the list to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note that if the list is empty, it returns NULL. + */ +#define list_pop(list, type, member) \ +({ \ + struct list_head *head__ = (list); \ + struct list_head *pos__ = READ_ONCE(head__->next); \ + type *entry__ = NULL; \ + \ + if (pos__ != head__) { \ + entry__ = list_entry(pos__, type, member); \ + list_del(pos__); \ + } \ + \ + entry__; \ +}) + /** * list_next_entry - get the next element in list * @pos: the type * to cursor
We have a very common pattern where we want to delete the first entry from a list and return it as the properly typed container structure. Add a list_pop helper to implement this behavior. Signed-off-by: Christoph Hellwig <hch@lst.de> --- include/linux/list.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)