[PATCH 1/4] utils: Document wl_container_of

Aaron Faanes dafrito at gmail.com
Wed Aug 28 16:01:59 PDT 2013


The explanation added is admittedly verbose (and reads more like a
proof), but my hope is that the comment should demystify how
wl_container_of works for those not familiar with the technique used.
Understanding this function also helps understanding how wl_list works.
---
 src/wayland-util.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/src/wayland-util.h b/src/wayland-util.h
index e5e4e25..02d9458 100644
--- a/src/wayland-util.h
+++ b/src/wayland-util.h
@@ -110,6 +110,51 @@ 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);
 
+/**
+ * Retrieves a pointer to the content of a wl_list item.
+ *
+ * The ptr is a pointer to the wl_list item.
+ *
+ * The sample must be a pointer to the type of content that the list item
+ * stores, though it need not be a "valid" pointer; a null pointer will
+ * suffice.
+ *
+ * The member is the named location of ptr within the content.
+ *
+ * For instance, using the example above, assume the following list of
+ * integers:
+ *
+ * 	struct item_t {
+ * 		int foo;
+ * 		struct wl_list link;
+ * 	};
+ *
+ * Which lays out this content in memory like so:
+ *
+ * [content......][wl_list item][trailing content...]
+ *
+ * To retrieve a pointer to content given a pointer to its link, you would
+ * need to retrieve this size:
+ *
+ * [content......][wl_list item][trailing content...]
+ * ^-------------^
+ *
+ * Since we know the link is within item_t, we can retrieve a relative
+ * position of that link using subtraction:
+ *
+ * struct item_t *sample = NULL;
+ * offset = &(sample->link) - sample;
+ *
+ * This offset will be valid even if sample is a null or invalid pointer since
+ * we never dereference it; we only perform pointer arithmetic on it.
+ *
+ * Finally, with the offset and the given link, we can retrieve a pointer to
+ * content and complete the macro:
+ *
+ * content = link - offset;
+ * content = link - (&(sample->link) - sample);
+ * content = ptr  - (&(sample->member) - sample);
+ */
 #ifdef __GNUC__
 #define wl_container_of(ptr, sample, member)				\
 	(__typeof__(sample))((char *)(ptr)	-			\
-- 
1.8.3.1



More information about the wayland-devel mailing list