From: Yong Bakos <yba...@humanoriented.com> Add doxygen comment blocks to all wl_list methods.
Signed-off-by: Yong Bakos <yba...@humanoriented.com> --- v2: Refine the writing for clarity. Add dox for wl_list macros, omitted in v1. Add notices for unsafe operations and invalid states (giucam, pq) src/wayland-util.h | 213 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 177 insertions(+), 36 deletions(-) diff --git a/src/wayland-util.h b/src/wayland-util.h index cacc122..d8f9394 100644 --- a/src/wayland-util.h +++ b/src/wayland-util.h @@ -78,115 +78,232 @@ struct wl_interface { /** \class wl_list * - * \brief doubly-linked list + * \brief Circular doubly-linked list * - * The list head is of "struct wl_list" type, and must be initialized - * using wl_list_init(). All entries in the list must be of the same - * type. The item type must have a "struct wl_list" member. This - * member will be initialized by wl_list_insert(). There is no need to - * call wl_list_init() on the individual item. To query if the list is - * empty in O(1), use wl_list_empty(). + * On its own, an instance of `struct wl_list` represents the sentinel head of + * a circular, doubly-linked list, and must be initialized using wl_list_init(). + * When empty, the list head's `next` and `prev` members point to the list head + * itself, otherwise `next` references the first item in the list, and `prev` + * refers to the last item in the list. * - * Let's call the list reference "struct wl_list foo_list", the item type as - * "item_t", and the item member as "struct wl_list link". + * Use the `struct wl_list` type to represent both the list head and the links + * between items within the list. Use wl_list_empty() to determine if the list + * is empty in O(1). + * + * All items in the list must be of the same type. The item type must have a + * `struct wl_list` member, often named `link` by convention. There is no need + * to initialize an item's `link` - invoking wl_list_init() on an individual + * list item's `struct wl_list` member is unnecessary. + * + * Consider a list reference `struct wl_list foo_list`, an item type as + * `struct item_t`, and an item's link member as `struct wl_list link`. + * + * The following code initializes a list and adds three items to it. * - * The following code will initialize a list: * \code * struct wl_list foo_list; * * struct item_t { - * int foo; - * struct wl_list link; + * int foo; + * struct wl_list link; * }; * struct item_t item1, item2, item3; * * wl_list_init(&foo_list); - * wl_list_insert(&foo_list, &item1.link); // Pushes item1 at the head - * wl_list_insert(&foo_list, &item2.link); // Pushes item2 at the head - * wl_list_insert(&item2.link, &item3.link); // Pushes item3 after item2 + * wl_list_insert(&foo_list, &item1.link); // item1 is the first item + * wl_list_insert(&foo_list, &item2.link); // item2 is now the first item + * wl_list_insert(&item2.link, &item3.link); // insert item3 after item2 * \endcode * - * The list now looks like [item2, item3, item1] + * The list now looks like <em>[item2, item3, item1]</em>. + * + * The `wl_list` API provides some iterator macros. For example, to iterate + * a list in ascending order: * - * Iterate the list in ascending order: * \code * item_t *item; * wl_list_for_each(item, foo_list, link) { - * Do_something_with_item(item); + * do_something_with_item(item); * } * \endcode + * + * See the documentation of each iterator for details. + * \sa http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/list.h */ struct wl_list { struct wl_list *prev; struct wl_list *next; }; +/** + * Initializes the list. + * + * \param list List to initialize + * + * \memberof wl_list + */ void wl_list_init(struct wl_list *list); +/** + * Inserts an item into the list, after the item represented by \p list. + * When \p list is a reference to the list itself (the head), set the containing + * struct of \p elm as the first item in the list. + * + * \note If \p elm is already part of a list, inserting it again will lead to + * list corruption. + * + * \param list List item after which the new item is inserted + * \param elm Link of the containing struct to insert into the list + * + * \memberof wl_list + */ void wl_list_insert(struct wl_list *list, struct wl_list *elm); +/** + * Removes an item from the list. + * + * \note This operation leaves \p elm in an invalid state where its `prev` and + * `next` point to `NULL`. + * + * \param elm Link of the containing struct to remove from the list + * + * \memberof wl_list + */ void wl_list_remove(struct wl_list *elm); +/** + * Determines the length of the list. + * + * \note This is an O(n) operation. + * + * \param list List whose length is to be determined + * + * \return Number of items in the list + * + * \memberof wl_list + */ int wl_list_length(const struct wl_list *list); +/** + * Determines if the list is empty. + * + * \param list List whose emptiness is to be determined + * + * \return 1 if empty, or 0 if not empty + * + * \memberof wl_list + */ int wl_list_empty(const struct wl_list *list); +/** + * Inserts all of the items of one list into another, after the item represented + * by \p list. + * + * \note This leaves \p other itself in an invalid state. + * + * \param list List item after which the other list items will be inserted + * \param other List of items to insert + * + * \memberof wl_list + */ void wl_list_insert_list(struct wl_list *list, struct wl_list *other); /** - * Retrieves a pointer to the containing struct of a given member item. + * Retrieves a pointer to a containing struct, given a member name. * - * This macro allows conversion from a pointer to a item to its containing + * This macro allows "conversion" from a pointer to a member to its containing * struct. This is useful if you have a contained item like a wl_list, - * wl_listener, or wl_signal, provided via a callback or other means and would + * wl_listener, or wl_signal, provided via a callback or other means, and would * like to retrieve the struct that contains it. * + * \note If this macro causes problems on your compiler you might be + * able to find an alternative name for the non-standard `__typeof__` + * operator and add a special case of your own. + * * To demonstrate, the following example retrieves a pointer to * `example_container` given only its `destroy_listener` member: * * \code * struct example_container { - * struct wl_listener destroy_listener; - * // other members... + * struct wl_listener destroy_listener; + * // other members... * }; * * void example_container_destroy(struct wl_listener *listener, void *data) * { - * struct example_container *ctr; + * struct example_container *ctr; * - * ctr = wl_container_of(listener, ctr, destroy_listener); - * // destroy ctr... + * ctr = wl_container_of(listener, ctr, destroy_listener); + * // destroy ctr... * } * \endcode * - * \param ptr A valid pointer to the contained item. + * \note `sample` need not be a valid pointer. A null or uninitialised pointer + * is sufficient. * - * \param sample A pointer to the type of content that the list item - * stores. Sample does not need be a valid pointer; a null or - * an uninitialised pointer will suffice. + * \param ptr Valid pointer to the contained member + * \param sample Pointer to a struct whose type contains \p ptr + * \param member Named location of \p ptr within the \p sample type * - * \param member The named location of ptr within the sample type. - * - * \return The container for the specified pointer. + * \return The container for the specified pointer */ #define wl_container_of(ptr, sample, member) \ (__typeof__(sample))((char *)(ptr) - \ offsetof(__typeof__(*sample), member)) -/* If the above macro causes problems on your compiler you might be - * able to find an alternative name for the non-standard __typeof__ - * operator and add a special case here */ +/** + * Iterates over a list. + * + * 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 item in the list to \p pos, which can then be referenced in + * a trailing code block. For example, given a wl_list of `struct message` + * items: + * + * \code + * struct message { + * char *contents; + * wl_list link; + * }; + * + * struct wl_list *messages; + * // Assume messages now "contains" many messages + * + * struct message *m; + * wl_list_for_each(m, messages, link) { + * do_something_with_message(m); + * } + * \endcode + * + * \param pos Cursor that each list item will be assigned to + * \param head Head of the list to enumerate + * \param member Name of the link member within the item struct + * + * \memberof wl_list + */ #define wl_list_for_each(pos, head, member) \ 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, safe against removal of the list item. + * + * \sa wl_list_for_each() + * + * \param pos Cursor that each list item will be assigned to + * \param tmp Temporary pointer of the same type as \p pos + * \param head Head of the list to enumerate + * \param member Name of the link member within the item struct + * + * \memberof wl_list + */ #define wl_list_for_each_safe(pos, tmp, head, member) \ for (pos = wl_container_of((head)->next, pos, member), \ tmp = wl_container_of((pos)->member.next, tmp, member); \ @@ -194,11 +311,35 @@ wl_list_insert_list(struct wl_list *list, struct wl_list *other); pos = tmp, \ tmp = wl_container_of(pos->member.next, tmp, member)) +/** + * Iterates backwards over a list. + * + * \sa wl_list_for_each() + * + * \param pos Cursor that each list item will be assigned to + * \param head Head of the list to enumerate + * \param member Name of the link member within the item struct + * + * \memberof wl_list + */ #define wl_list_for_each_reverse(pos, head, member) \ 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, safe against removal of the list + * item. + * + * \sa wl_list_for_each() + * + * \param pos Cursor that each list item will be assigned to + * \param tmp Temporary pointer of the same type as \p pos + * \param head Head of the list to enumerate + * \param member Name of the link member within the item struct + * + * \memberof wl_list + */ #define wl_list_for_each_reverse_safe(pos, tmp, head, member) \ for (pos = wl_container_of((head)->prev, pos, member), \ tmp = wl_container_of((pos)->member.prev, tmp, member); \ -- 2.7.2 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel