wl_list(3)

πŸ’… wl_list(3) β€” Library Functions Manual πŸŽ€

okay bestie so this is wl_list, a doubly-linked list from Wayland's library functions manual, and honestly? she's iconic. lowkey the whole wayland-util.h situation runs on her. let's get into it πŸ’–


✨ NAME ✨

wl_list β€” Doubly-linked list. that's it. that's the whole name. she's a doubly-linked list and she knows it πŸ‘‘


✨ SYNOPSIS ✨

#include <wayland-util.h>

🌸 Public Member Functions

  • void wl_list_init (struct wl_list *list)
  • void wl_list_insert (struct wl_list *list, struct wl_list *elm)
  • void wl_list_remove (struct wl_list *elm)
  • int wl_list_length (const struct wl_list *list)
  • int wl_list_empty (const struct wl_list *list)
  • void wl_list_insert_list (struct wl_list *list, struct wl_list *other)

πŸ¦‹ Data Fields

  • struct wl_list * prev
  • struct wl_list * next

(ok so heads up: these are not member symbols, they're their own little thing πŸ’«)

  • #define wl_list_for_each(pos, head, member)
  • #define wl_list_for_each_safe(pos, tmp, head, member)
  • #define wl_list_for_each_reverse(pos, head, member)
  • #define wl_list_for_each_reverse_safe(pos, tmp, head, member)

✨ Detailed Description ✨

Doubly-linked list. fr fr. 🫢

so like, on its own, an instance of struct wl_list represents the sentinel head of a doubly-linked list, and you must initialize it using wl_list_init(). that part is not optional, bestie. when empty, the list head's next and prev members point to the list head itself (self-obsessed queen behavior, honestly πŸ’…). otherwise next references the first element in the list, and prev refers to the last element in the list.

use the struct wl_list type to represent both the list head and the links between elements within the list. use wl_list_empty() to determine if the list is empty in O(1) β€” yes, constant time, she's efficient like that ⚑

all elements in the list must be of the same type. no mixing, no matching, this isn't a thrift haul. the element type must have a struct wl_list member, often named link by convention (convention! say it with me: link πŸ”—).

prior to insertion, there is no need to initialize an element's link β€” invoking wl_list_init() on an individual list element's struct wl_list member is unnecessary if the very next operation is wl_list_insert(). however, a common idiom is to initialize an element's link prior to removal β€” ensure safety by invoking wl_list_init() before wl_list_remove(). safety first, always πŸ›Ÿ

consider a list reference struct wl_list foo_list, an element type as struct element, and an element's link member as struct wl_list link.

the following code initializes a list and adds three elements to it:

struct wl_list foo_list;

struct element {
        int foo;
        struct wl_list link;
};
struct element e1, e2, e3;

wl_list_init(&foo_list);
wl_list_insert(&foo_list, &e1.link);   // e1 is the first element
wl_list_insert(&foo_list, &e2.link);   // e2 is now the first element
wl_list_insert(&e2.link, &e3.link); // insert e3 after e2

the list now looks like [e2, e3, e1]. slay. look at her go πŸŽ‰

the wl_list API provides some iterator macros. for example, to iterate a list in ascending order:

struct element *e;
wl_list_for_each(e, foo_list, link) {
        do_something_with_element(e);
}

see the documentation of each iterator for details πŸ‘€

🧚 See also

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/list.h


✨ Member Function Documentation ✨

πŸ’œ int wl_list_empty (const struct wl_list * list)

Determines if the list is empty. the vibe check function, basically πŸ•΅οΈ

Parameters

  • list β€” List whose emptiness is to be determined

Returns

1 if empty, or 0 if not empty


πŸ’œ void wl_list_init (struct wl_list * list)

Initializes the list. every queen needs her origin story ✨

Parameters

  • list β€” List to initialize

πŸ’œ void wl_list_insert (struct wl_list * list, struct wl_list * elm)

Inserts an element into the list, after the element represented by list. when list is a reference to the list itself (the head), set the containing struct of elm as the first element in the list. so she goes to the front of the line, main character energy πŸ‘‘

Note β€” If elm is already part of a list, inserting it again will lead to list corruption. 😭 no cap, do NOT do this. that's the whole list ruined. catastrophic. we don't do that here πŸ’€

Parameters

  • list β€” List element after which the new element is inserted
  • elm β€” Link of the containing struct to insert into the list

πŸ’œ void wl_list_insert_list (struct wl_list * list, struct wl_list * other)

Inserts all of the elements of one list into another, after the element represented by list. bulk move, she's bringing the whole friend group πŸ«‚

Note β€” This leaves other in an invalid state. like, genuinely don't touch it after. it's done. it's over. πŸ™ˆ

Parameters

  • list β€” List element after which the other list elements will be inserted
  • other β€” List of elements to insert

πŸ’œ int wl_list_length (const struct wl_list * list)

Determines the length of the list.

Note β€” This is an O(n) operation. ngl bestie, don't call this in a hot loop unless you mean it 😭

Parameters

  • list β€” List whose length is to be determined

Returns

Number of elements in the list


πŸ’œ void wl_list_remove (struct wl_list * elm)

Removes an element from the list. goodbye, we barely knew ye πŸ‘‹

Note β€” This operation leaves elm in an invalid state. pls don't go dereferencing it afterwards, that's a one-way ticket to undefined behavior town πŸ’€

Parameters

  • elm β€” Link of the containing struct to remove from the list

Value:

for (pos = wl_container_of((head)->next, pos, member);  \
     &pos->member != (head);                                    \
     pos = wl_container_of(pos->member.next, pos, member))

Iterates over a list. the classic. the blueprint. the OG ✨

this macro expresses a for-each iterator for wl_list. given a list and wl_list link member name (often named link by convention), this macro assigns each element in the list to pos, which can then be referenced in a trailing code block. for example, given a wl_list of struct message elements:

struct message {
        char *contents;
        wl_list link;
};

struct wl_list *message_list;
// Assume message_list now "contains" many messages

struct message *m;
wl_list_for_each(m, message_list, link) {
        do_something_with_message(m);
}

Parameters

  • pos β€” Cursor that each list element will be assigned to
  • head β€” Head of the list to iterate over
  • member β€” Name of the link member within the element struct

Value:

for (pos = wl_container_of((head)->prev, pos, member);  \
     &pos->member != (head);                                    \
     pos = wl_container_of(pos->member.prev, pos, member))

Iterates backwards over a list. she's walking in reverse and she's still slaying πŸ’…

See also

wl_list_for_each()

Parameters

  • pos β€” Cursor that each list element will be assigned to
  • head β€” Head of the list to iterate over
  • member β€” Name of the link member within the element struct

Value:

for (pos = wl_container_of((head)->prev, pos, member),  \
     tmp = wl_container_of((pos)->member.prev, tmp, member);    \
     &pos->member != (head);                                    \
     pos = tmp,                                                 \
     tmp = wl_container_of(pos->member.prev, tmp, member))

Iterates backwards over a list, safe against removal of the list element. backwards and safe. she's got range 🌈

Note β€” Only removal of the current element, pos, is safe. Removing any other element during traversal may lead to a loop malfunction. so like, stay in your lane, only remove pos 😀

See also

wl_list_for_each()

Parameters

  • pos β€” Cursor that each list element will be assigned to
  • tmp β€” Temporary pointer of the same type as pos
  • head β€” Head of the list to iterate over
  • member β€” Name of the link member within the element struct

Value:

for (pos = wl_container_of((head)->next, pos, member),          \
     tmp = wl_container_of((pos)->member.next, tmp, member);    \
     &pos->member != (head);                                    \
     pos = tmp,                                                 \
     tmp = wl_container_of(pos->member.next, tmp, member))

Iterates over a list, safe against removal of the list element. the safe version of the classic. glow up πŸ¦‹

Note β€” Only removal of the current element, pos, is safe. Removing any other element during traversal may lead to a loop malfunction. same rule as her reverse twin, no exceptions πŸ™…β€β™€οΈ

See also

wl_list_for_each()

Parameters

  • pos β€” Cursor that each list element will be assigned to
  • tmp β€” Temporary pointer of the same type as pos
  • head β€” Head of the list to iterate over
  • member β€” Name of the link member within the element struct

✨ Field Documentation ✨

🌸 struct wl_list* wl_list::next

Next list element ➑️

🌸 struct wl_list* wl_list::prev

Previous list element ⬅️


✨ Author ✨

Generated automatically by Doxygen for Wayland from the source code. not a human, not a vibe curator, just doxygen doing her lil thing πŸ€–πŸ’–


and that's the page bestie!! πŸŽ€ source/version: Wayland, Version 1.26.0, straight out of the library functions manual β€” mwah, go write some linked lists, ily πŸ«ΆπŸ’œ

πŸ“¦ where this page comes from