* @suffix: the name to use (struct tlist_@suffix)
* @type: the type the list will contain (void for any type)
*
- * This declares a structure "struct tlist_@suffix" to use for
- * lists containing this type. The actual list can be accessed using
- * ".raw" or tlist_raw().
+ * This declares a structure "struct tlist_@suffix" to use for lists
+ * containing this type. The actual list can be accessed using
+ * tlist_raw(). For maximum portability, place tlists embedded in
+ * structures as the last member.
*
* Example:
* // Defines struct tlist_children
* TLIST_TYPE(children, struct child);
* struct parent {
* const char *name;
- * struct tlist_children children;
* unsigned int num_children;
+ * struct tlist_children children;
* };
*
* struct child {
*/
#define TLIST_TYPE(suffix, type) \
struct tlist_##suffix { \
- struct list_head raw; \
- TCON(type *canary); \
+ TCON_WRAP(struct list_head, type *canary); \
}
/**
- * TLIST_INIT - initalizer for an empty tlist
+ * TLIST_INIT - initializer for an empty tlist
* @name: the name of the list.
*
* Explicit initializer for an empty list.
* Example:
* static struct tlist_children my_list = TLIST_INIT(my_list);
*/
-#define TLIST_INIT(name) { LIST_HEAD_INIT(name.raw) }
+#define TLIST_INIT(name) TCON_WRAP_INIT(LIST_HEAD_INIT(*tcon_unwrap(&name)))
/**
* tlist_check - check head of a list for consistency
* }
*/
#define tlist_check(h, abortstr) \
- list_check(&(h)->raw, (abortstr))
+ list_check(tcon_unwrap(h), (abortstr))
/**
* tlist_init - initialize a tlist
* tlist_init(&parent->children);
* parent->num_children = 0;
*/
-#define tlist_init(h) list_head_init(&(h)->raw)
+#define tlist_init(h) list_head_init(tcon_unwrap(h))
/**
* tlist_raw - unwrap the typed list and check the type
* variable is of an unexpected type. It is used internally where we
* need to access the raw underlying list.
*/
-#define tlist_raw(h, expr) (&tcon_check((h), canary, (expr))->raw)
+#define tlist_raw(h, expr) tcon_unwrap(tcon_check((h), canary, (expr)))
/**
* tlist_add - add an entry at the start of a linked list.
* Example:
* assert(tlist_empty(&parent->children) == (parent->num_children == 0));
*/
-#define tlist_empty(h) list_empty(&(h)->raw)
+#define tlist_empty(h) list_empty(tcon_unwrap(h))
/**
* tlist_top - get the first entry in a list
* @h: the tlist
- * @type: the type of the entry
* @member: the list_node member of the type
*
* If the list is empty, returns NULL.
*
* Example:
* struct child *first;
- * first = tlist_top(&parent->children, struct child, list);
+ * first = tlist_top(&parent->children, list);
+ * if (!first)
+ * printf("Empty list!\n");
*/
-#define tlist_top(h, type, member) \
- list_top(tlist_raw((h), (type *)NULL), type, member)
+#define tlist_top(h, member) \
+ ((tcon_type((h), canary)) \
+ list_top_(tcon_unwrap((h)), \
+ (char *)(&(h)->_tcon[0].canary->member) - \
+ (char *)((h)->_tcon[0].canary)))
/**
* tlist_tail - get the last entry in a list
* @h: the tlist
- * @type: the type of the entry
* @member: the list_node member of the type
*
* If the list is empty, returns NULL.
*
* Example:
* struct child *last;
- * last = tlist_tail(&parent->children, struct child, list);
+ * last = tlist_tail(&parent->children, list);
+ * if (!last)
+ * printf("Empty list!\n");
+ */
+#define tlist_tail(h, member) \
+ ((tcon_type((h), canary)) \
+ list_tail_(tcon_unwrap(h), \
+ (char *)(&(h)->_tcon[0].canary->member) - \
+ (char *)((h)->_tcon[0].canary)))
+
+/**
+ * tlist_next - get the next entry in a list
+ * @h: the tlist
+ * @n: the list element
+ * @member: the list_node member of the type
+ *
+ * Returns the element of list @h immediately after @n, or NULL, if @n
+ * is the last element in the list.
+ */
+#define tlist_next(h, n, member) \
+ list_next(tlist_raw((h), (n)), (n), member)
+
+/**
+ * tlist_prev - get the previous entry in a list
+ * @h: the tlist
+ * @n: the list element
+ * @member: the list_node member of the type
+ *
+ * Returns the element of list @h immediately before @n, or NULL, if
+ * @n is the first element in the list.
*/
-#define tlist_tail(h, type, member) \
- list_tail(tlist_raw((h), (type *)NULL), type, member)
+#define tlist_prev(h, n, member) \
+ list_prev(tlist_raw((h), (n)), (n), member)
/**
* tlist_for_each - iterate through a list.
#define tlist_for_each(h, i, member) \
list_for_each(tlist_raw((h), (i)), (i), member)
+/**
+ * tlist_for_each - iterate through a list backwards.
+ * @h: the tlist
+ * @i: an iterator of suitable type for this list.
+ * @member: the list_node member of @i
+ *
+ * This is a convenient wrapper to iterate @i over the entire list. It's
+ * a for loop, so you can break and continue as normal.
+ *
+ * Example:
+ * tlist_for_each_rev(&parent->children, child, list)
+ * printf("Name: %s\n", child->name);
+ */
+#define tlist_for_each_rev(h, i, member) \
+ list_for_each_rev(tlist_raw((h), (i)), (i), member)
+
/**
* tlist_for_each_safe - iterate through a list, maybe during deletion
* @h: the tlist