eina: Add detailed description and some examples to Eina_Inlist.
authorantognolli <antognolli@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 14 Jun 2011 17:43:53 +0000 (17:43 +0000)
committerantognolli <antognolli@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 14 Jun 2011 17:43:53 +0000 (17:43 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eina@60310 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

12 files changed:
doc/img/eina_inlist-node.png [new file with mode: 0644]
doc/img/eina_inlist-node_eg1-inlist.png [new file with mode: 0644]
doc/img/eina_inlist-node_eg1-my-struct.png [new file with mode: 0644]
doc/img/eina_inlist-node_eg2-list-inlist.png [new file with mode: 0644]
doc/img/eina_inlist-node_eg2-my-struct.png [new file with mode: 0644]
doc/img/eina_inlist-node_eg3-my-struct.png [new file with mode: 0644]
doc/img/eina_inlist-node_eg3-two-inlists.png [new file with mode: 0644]
src/examples/Makefile.am
src/examples/eina_inlist_01.c [new file with mode: 0644]
src/examples/eina_inlist_02.c [new file with mode: 0644]
src/examples/eina_inlist_03.c [new file with mode: 0644]
src/include/eina_inlist.h

diff --git a/doc/img/eina_inlist-node.png b/doc/img/eina_inlist-node.png
new file mode 100644 (file)
index 0000000..195497b
Binary files /dev/null and b/doc/img/eina_inlist-node.png differ
diff --git a/doc/img/eina_inlist-node_eg1-inlist.png b/doc/img/eina_inlist-node_eg1-inlist.png
new file mode 100644 (file)
index 0000000..48c0a47
Binary files /dev/null and b/doc/img/eina_inlist-node_eg1-inlist.png differ
diff --git a/doc/img/eina_inlist-node_eg1-my-struct.png b/doc/img/eina_inlist-node_eg1-my-struct.png
new file mode 100644 (file)
index 0000000..4393f2c
Binary files /dev/null and b/doc/img/eina_inlist-node_eg1-my-struct.png differ
diff --git a/doc/img/eina_inlist-node_eg2-list-inlist.png b/doc/img/eina_inlist-node_eg2-list-inlist.png
new file mode 100644 (file)
index 0000000..4eb3235
Binary files /dev/null and b/doc/img/eina_inlist-node_eg2-list-inlist.png differ
diff --git a/doc/img/eina_inlist-node_eg2-my-struct.png b/doc/img/eina_inlist-node_eg2-my-struct.png
new file mode 100644 (file)
index 0000000..9183197
Binary files /dev/null and b/doc/img/eina_inlist-node_eg2-my-struct.png differ
diff --git a/doc/img/eina_inlist-node_eg3-my-struct.png b/doc/img/eina_inlist-node_eg3-my-struct.png
new file mode 100644 (file)
index 0000000..f669afd
Binary files /dev/null and b/doc/img/eina_inlist-node_eg3-my-struct.png differ
diff --git a/doc/img/eina_inlist-node_eg3-two-inlists.png b/doc/img/eina_inlist-node_eg3-two-inlists.png
new file mode 100644 (file)
index 0000000..c8d2c8b
Binary files /dev/null and b/doc/img/eina_inlist-node_eg3-two-inlists.png differ
index fb0fa2f..e8b14b4 100644 (file)
@@ -20,7 +20,10 @@ SRCS = \
        eina_list_01.c \
        eina_list_02.c \
        eina_list_03.c \
-       eina_list_04.c
+       eina_list_04.c \
+       eina_inlist_01.c \
+       eina_inlist_02.c \
+       eina_inlist_03.c
 
 pkglib_PROGRAMS =
 
@@ -40,6 +43,9 @@ pkglib_PROGRAMS += \
        eina_list_01 \
        eina_list_02 \
        eina_list_03 \
-       eina_list_04
+       eina_list_04 \
+       eina_inlist_01 \
+       eina_inlist_02 \
+       eina_inlist_03
 endif
 
diff --git a/src/examples/eina_inlist_01.c b/src/examples/eina_inlist_01.c
new file mode 100644 (file)
index 0000000..fa51553
--- /dev/null
@@ -0,0 +1,96 @@
+// Compile with:
+// gcc -g `pkg-config --cflags --libs eina` eina_inlist_01.c -o eina_inlist_01
+#include <Eina.h>
+#include <stdio.h>
+
+struct my_struct {
+     EINA_INLIST;
+     int a, b;
+};
+
+int
+sort_cb(const void *d1, const void *d2)
+{
+   const Eina_Inlist *l1, *l2;
+   const struct my_struct *x1, *x2;
+
+   l1 = d1;
+   l2 = d2;
+
+   x1 = EINA_INLIST_CONTAINER_GET(l1, struct my_struct);
+   x2 = EINA_INLIST_CONTAINER_GET(l2, struct my_struct);
+
+   return x1->a - x2->a;
+}
+
+int
+main(void)
+{
+   struct my_struct *d, *cur;
+   Eina_Inlist *list, *itr, *tmp;
+
+   eina_init();
+
+   d = malloc(sizeof(*d));
+   d->a = 1;
+   d->b = 10;
+   list = eina_inlist_append(NULL, EINA_INLIST_GET(d));
+
+   d = malloc(sizeof(*d));
+   d->a = 2;
+   d->b = 20;
+   list = eina_inlist_append(list, EINA_INLIST_GET(d));
+
+   d = malloc(sizeof(*d));
+   d->a = 3;
+   d->b = 30;
+   list = eina_inlist_prepend(list, EINA_INLIST_GET(d));
+
+   printf("list=%p\n", list);
+   EINA_INLIST_FOREACH(list, cur)
+     printf("\ta=%d, b=%d\n", cur->a, cur->b);
+
+   list = eina_inlist_promote(list, EINA_INLIST_GET(d));
+
+   d = malloc(sizeof(*d));
+   d->a = 4;
+   d->b = 40;
+   list = eina_inlist_append_relative(list, EINA_INLIST_GET(d), list);
+
+   list = eina_inlist_demote(list, EINA_INLIST_GET(d));
+
+   list = eina_inlist_sort(list, sort_cb);
+
+   printf("list after sort=%p\n", list);
+   EINA_INLIST_FOREACH(list, cur)
+     printf("\ta=%d, b=%d\n", cur->a, cur->b);
+
+   tmp = eina_inlist_find(list, EINA_INLIST_GET(d));
+   if (tmp)
+     cur = EINA_INLIST_CONTAINER_GET(tmp, struct my_struct);
+   else
+     cur = NULL;
+
+   if (d != cur)
+     printf("wrong node! cur=%p\n", cur);
+
+   list = eina_inlist_remove(list, EINA_INLIST_GET(d));
+   free(d);
+   printf("list=%p\n", list);
+   for (itr = list; itr != NULL; itr = itr->next)
+     {
+        cur = EINA_INLIST_CONTAINER_GET(itr, struct my_struct);
+        printf("\ta=%d, b=%d\n", cur->a, cur->b);
+     }
+
+   while (list)
+     {
+        Eina_Inlist *aux = list;
+        list = eina_inlist_remove(list, list);
+        free(aux);
+     }
+
+   eina_shutdown();
+
+   return 0;
+}
diff --git a/src/examples/eina_inlist_02.c b/src/examples/eina_inlist_02.c
new file mode 100644 (file)
index 0000000..7d23f13
--- /dev/null
@@ -0,0 +1,64 @@
+// Compile with:
+// gcc -g `pkg-config --cflags --libs eina` eina_inlist_01.c -o eina_inlist_01
+#include <Eina.h>
+#include <stdio.h>
+
+struct my_struct {
+     EINA_INLIST;
+     int a, b;
+};
+
+int
+main(void)
+{
+   struct my_struct *d, *cur;
+   int i;
+
+   Eina_Inlist *inlist = NULL;
+   Eina_List *list = NULL, *l_itr, *l_next;
+
+   eina_init();
+
+   for (i = 0; i < 100; i++)
+     {
+       d = malloc(sizeof(*d));
+       d->a = i;
+       d->b = i * 10;
+       inlist = eina_inlist_append(inlist, EINA_INLIST_GET(d));
+       if ((i % 2) == 0)
+         list = eina_list_prepend(list, d);
+     }
+
+   printf("inlist=%p\n", inlist);
+   EINA_INLIST_FOREACH(inlist, cur)
+     printf("\ta=%d, b=%d\n", cur->a, cur->b);
+
+   printf("list=%p\n", list);
+   EINA_LIST_FOREACH(list, l_itr, cur)
+     printf("\ta=%d, b=%d\n", cur->a, cur->b);
+
+   printf("inlist count=%d\n", eina_inlist_count(inlist));
+   printf("list count=%d\n\n", eina_list_count(list));
+
+   EINA_LIST_FOREACH_SAFE(list, l_itr, l_next, cur)
+     {
+       if ((cur->a % 3) == 0)
+         list = eina_list_remove_list(list, l_itr);
+     }
+
+   printf("inlist count=%d\n", eina_inlist_count(inlist));
+   printf("list count=%d\n\n", eina_list_count(list));
+
+   eina_list_free(list);
+
+   while (inlist)
+     {
+        Eina_Inlist *aux = inlist;
+        inlist = eina_inlist_remove(inlist, inlist);
+        free(aux);
+     }
+
+   eina_shutdown();
+
+   return 0;
+}
diff --git a/src/examples/eina_inlist_03.c b/src/examples/eina_inlist_03.c
new file mode 100644 (file)
index 0000000..a39a784
--- /dev/null
@@ -0,0 +1,73 @@
+// Compile with:
+// gcc -g `pkg-config --cflags --libs eina` eina_inlist_01.c -o eina_inlist_01
+#include <Eina.h>
+#include <stdio.h>
+
+struct my_struct {
+     EINA_INLIST;
+     Eina_Inlist even;
+     int a, b;
+};
+
+#define EVEN_INLIST_GET(Inlist) (& ((Inlist)->even))
+
+#define EVEN_INLIST_CONTAINER_GET(ptr, type) \
+   ((type *)((char *)ptr - offsetof(type, even)))
+
+int
+main(void)
+{
+   struct my_struct *d, *cur;
+   int i;
+
+   Eina_Inlist *list = NULL, *list_even = NULL, *itr;
+
+   eina_init();
+
+   for (i = 0; i < 100; i++)
+     {
+       d = malloc(sizeof(*d));
+       d->a = i;
+       d->b = i * 10;
+       list = eina_inlist_append(list, EINA_INLIST_GET(d));
+       if ((i % 2) == 0)
+         list_even = eina_inlist_prepend(list_even, EVEN_INLIST_GET(d));
+     }
+
+   printf("list=%p\n", list);
+   EINA_INLIST_FOREACH(list, cur)
+     printf("\ta=%d, b=%d\n", cur->a, cur->b);
+
+   printf("list_even=%p\n", list_even);
+   for (itr = list_even; itr != NULL; itr = itr->next)
+     {
+       cur = EVEN_INLIST_CONTAINER_GET(itr, struct my_struct);
+       printf("\ta=%d, b=%d\n", cur->a, cur->b);
+     }
+
+   printf("list count=%d\n", eina_inlist_count(list));
+   printf("list_even count=%d\n\n", eina_inlist_count(list_even));
+
+   itr = list_even;
+   while (itr)
+     {
+       Eina_Inlist *next = itr->next;
+       cur = EVEN_INLIST_CONTAINER_GET(itr, struct my_struct);
+       if ((cur->a % 3) == 0)
+         list_even = eina_inlist_remove(list_even, itr);
+       itr = next;
+     }
+   printf("list count=%d\n", eina_inlist_count(list));
+   printf("list_even count=%d\n\n", eina_inlist_count(list_even));
+
+   while (list)
+     {
+        Eina_Inlist *aux = list;
+        list = eina_inlist_remove(list, list);
+        free(aux);
+     }
+
+   eina_shutdown();
+
+   return 0;
+}
index eef0788..694226e 100644 (file)
 #include <stddef.h>
 
 /**
+ * @page inlist_01_example_page Eina_Inlist basic usage
+ * @dontinclude eina_inlist_01.c
+ *
+ * To see the full source for this example, click here: @ref
+ * eina_inlist_01_c
+ *
+ * As explained before, inline lists mean its nodes pointers are part of same
+ * memory block/blob. This is done by using the macro @ref EINA_INLIST inside the
+ * data structure that will be used:
+ *
+ * @skip struct
+ * @until };
+ *
+ * The resulting node representing this struct can be exemplified by the
+ * following picture:
+ *
+ * @image html eina_inlist-node_eg1-my-struct.png
+ * @image rtf eina_inlist-node_eg1-my-struct.png
+ *
+ * Let's define a comparison function that will be used later during the
+ * sorting of the list:
+ *
+ * @skip int
+ * @until }
+ *
+ * The @ref Eina_Inlist can be used exactly the same way as @ref Eina_List when
+ * appending, prepend and removing items. But since we already have the node
+ * pointers inside the structure, they need to be retrieved with the macro @ref
+ * EINA_INLIST_GET :
+ *
+ * @skip malloc
+ * @until append
+ *
+ * Notice that @ref eina_inlist_append always receives the head of the list as
+ * first argument, and its return value should be used as the list pointer
+ * (head):
+ *
+ * @skip malloc
+ * @until append
+ *
+ * After appending 3 items, the list now should look similar to this:
+ *
+ * @image html eina_inlist-node_eg1-inlist.png
+ * @image rtf eina_inlist-node_eg1-inlist.png
+ *
+ * The macro @ref EINA_INLIST_FOREACH can be used to iterate over the list:
+ *
+ * @skip printf
+ * @until cur->a
+ *
+ * @ref eina_inlist_promote(), @ref eina_inlist_demote(), @ref
+ * eina_inlist_append_relative() and similar functions all work in the same way
+ * as the @ref Eina_List :
+ *
+ * @skip eina_inlist_promote
+ * @until eina_inlist_demote
+ *
+ * Now let's use the @c sort_cb function declared above to sort our list:
+ *
+ * @skipline eina_inlist_sort
+ *
+ * Removing an element from the inlist is also similar to @ref Eina_List :
+ *
+ * @skip inlist_remove
+ * @until free
+ *
+ * Another way of walking through the inlist.
+ *
+ * @skip for
+ * @until }
+ *
+ * Notice that in the previous piece of code, since we only have the pointers to
+ * the inlist nodes, we have to use the @ref EINA_INLIST_CONTAINER_GET macro
+ * that will return the pointer to the entire structure. Of course, in this case
+ * it is the same as the list pointer, since the @ref EINA_INLIST macro was used
+ * in the beginning of the structure.
+ *
+ * Now to finish this example, lets delete this list:
+ *
+ * @skip while
+ * @until }
+ */
+
+/**
+ * @page inlist_02_example_page Eina_Inlist advanced usage - lists and inlists
+ * @dontinclude eina_inlist_02.c
+ *
+ * This example describes the usage of @ref Eina_Inlist mixed with @ref
+ * Eina_List . We create and add elements to an inlist, and the even members
+ * are also added to a normal list. Later we remove the elements divisible by 3
+ * from this normal list.
+ *
+ * The struct that is going to be used is the same used in @ref
+ * inlist_01_example_page , since we still need the @ref EINA_INLIST macro to
+ * declare the inlist node info:
+ *
+ * @skip struct
+ * @until };
+ *
+ * The resulting node representing this struct can be exemplified by the
+ * following picture:
+ *
+ * @image html eina_inlist-node_eg2-my-struct.png
+ * @image rtf eina_inlist-node_eg2-my-struct.png
+ *
+ * Now we need some pointers and auxiliar variables that will help us iterate on
+ * the lists:
+ *
+ * @skip struct
+ * @until l_next;
+ *
+ * Allocating 100 elements and putting them into an inlist, and the even
+ * elements also go to the normal list:
+ *
+ * @skip for
+ * @until }
+ *
+ * After this point, what we have are two distinct lists that share some
+ * elements. The first list (inlist) is defined by the pointers inside the
+ * elements data structure, while the second list (normal list) has its own node
+ * data structure that is kept outside of the elements.
+ *
+ * The two lists, sharing some elements, can be represented by the following
+ * picture:
+ *
+ * <img src="eina_inlist-node_eg2-list-inlist.png" width="100%"/>
+ * @image rtf eina_inlist-node_eg2-list-inlist.png
+ *
+ * Accessing both lists is done normally, as if they didn't have any elements in
+ * common:
+ *
+ * @skip printf
+ * @until eina_list_count
+ *
+ * We can remove elements from the normal list, but we just don't free them
+ * because they are still stored in the inlist:
+ *
+ * @skip EINA_LIST_FOREACH_SAFE
+ * @until eina_list_count
+ *
+ * To finish this example, we want to free both lists, we can't just free all
+ * elements on the second list (normal list) because they are still being used
+ * in the inlist. So we first discard the normal list without freeing its
+ * elements, then we free all elements in the inlist (that contains all elements
+ * allocated until now):
+ *
+ * @skip eina_list_free
+ * @until }
+ *
+ * Here is the full source code for this example: @ref eina_inlist_02_c
+ */
+
+/**
+ * @page inlist_03_example_page Eina_Inlist advanced usage - multi-inlists
+ * @dontinclude eina_inlist_03.c
+ *
+ * This example describes the usage of multiple inlists storing the same data.
+ * It means that some data may appear in more than one inlist at the same time.
+ * We will demonstrate this by creating an inlist with 100 numbers, and adding
+ * the odd numbers to the second inlist, then remove the numbers divisible by 3
+ * from the second list.
+ *
+ * To accomplish this, it is necessary to have two inlist pointers in the struct
+ * that is going to be stored. We are using the default inlist member @ref
+ * EINA_INLIST, and adding another member @c even that is of type @ref
+ * Eina_Inlist too:
+ *
+ * @skip struct
+ * @until };
+ *
+ * The representation for this struct is:
+ *
+ * @image html eina_inlist-node_eg3-my-struct.png
+ * @image rtf eina_inlist-node_eg3-my-struct.png
+ *
+ * And we will define some convenience macros that are equivalent to @ref
+ * EINA_INLIST_GET and @ref EINA_INLIST_CONTAINER_GET :
+ *
+ * @skip define
+ * @until offsetof
+ *
+ * We need two pointers, one for each list, and a pointer that will be used as
+ * an iterator:
+ *
+ * @skipline Eina_Inlist
+ *
+ * Now we allocate and add to the first list every number from 0 to 99. These
+ * nodes data also have the @ref Eina_Inlist node info for the second list (@c
+ * even). We will use them to add just the even numbers to the second list, the
+ * @c list_even. Also notice that we are using our macro @c EVEN_INLIST_GET to
+ * get the pointer to the even list node info:
+ *
+ * @skip for
+ * @until }
+ *
+ * And the resulting lists will be as follow:
+ *
+ * <img src="eina_inlist-node_eg3-two-inlists.png" width="100%"/>
+ * @image rtf eina_inlist-node_eg3-two-inlists.png
+ *
+ * For the first list, we can use the macro @ref EINA_INLIST_FOREACH to iterate
+ * over its elements:
+ *
+ * @skip FOREACH
+ * @until printf
+ *
+ * But for the second list, we have to do it manually. Of course we could create
+ * a similar macro to @ref EINA_INLIST_FOREACH, but since this macro is more
+ * complex than the other two and we are using it only once, it's better to just
+ * do it manually:
+ *
+ * @skip for
+ * @until }
+ *
+ * Let's just check that the two lists have the expected number of elements:
+ *
+ * @skip list count
+ * @until list_even count
+ *
+ * And removing the numbers divisible by 3 only from the second list:
+ *
+ * @skip itr
+ * @until list_even count
+ *
+ * Now that we don't need the two lists anymore, we can just free all the items.
+ * Since all of the allocated data was put into the first list, and both lists
+ * are made of pointers to inside the data structures, we can free only the
+ * first list (that contains all the elements) and the second list will be gone
+ * with it:
+ *
+ * @skip while
+ * @until free
+ *
+ * To see the full source code for this example, click here: @ref
+ * eina_inlist_03_c
+ *
+ */
+
+/**
+ * @page eina_inlist_01_c eina_inlist_01.c
+ * @include eina_inlist_01.c
+ */
+
+/**
+ * @page eina_inlist_02_c eina_inlist_02.c
+ * @include eina_inlist_02.c
+ */
+
+/**
+ * @page eina_inlist_03_c eina_inlist_03.c
+ * @include eina_inlist_03.c
+ */
+
+/**
  * @addtogroup Eina_Inline_List_Group Inline List
  *
  * @brief These functions provide inline list management.
  *
  * Inline lists mean its nodes pointers are part of same memory as
  * data. This has the benefit of fragmenting memory less and avoiding
- * @c node->data indirection, but has the drawback of elements only
- * being able to be part of one single inlist at same time. But it is
- * possible to have inlist nodes to be part of regular lists created
- * with eina_list_append() or eina_list_prepend().
+ * @c node->data indirection, but has the drawback of higher cost for some
+ * common operations like count and sort.
+ *
+ * It is possible to have inlist nodes to be part of regular lists, created with
+ * @ref eina_list_append() or @ref eina_list_prepend(). It's also possible to
+ * have a structure with two inlist pointers, thus be part of two different
+ * inlists at the same time, but the current convenience macros provided won't
+ * work for both of them. Consult @ref inlist_advanced for more info.
  *
  * Inline lists have their purposes, but if you don't know what those purposes are, go with
  * regular lists instead.
  * This lets the compiler to do type checking and let the programmer know
  * exactly what type this list is.
  *
- * @code
- * #include <Eina.h>
- * #include <stdio.h>
- *
- * int
- * main(void)
- * {
- *    struct my_struct {
- *       EINA_INLIST;
- *       int a, b;
- *    } *d, *cur;
- *    Eina_Inlist *list, *itr;
- *
- *    eina_init();
- *
- *    d = malloc(sizeof(*d));
- *    d->a = 1;
- *    d->b = 10;
- *    list = eina_inlist_append(NULL, EINA_INLIST_GET(d));
- *
- *    d = malloc(sizeof(*d));
- *    d->a = 2;
- *    d->b = 20;
- *    list = eina_inlist_append(list, EINA_INLIST_GET(d));
- *
- *    d = malloc(sizeof(*d));
- *    d->a = 3;
- *    d->b = 30;
- *    list = eina_inlist_prepend(list, EINA_INLIST_GET(d));
- *
- *    printf("list=%p\n", list);
- *    EINA_INLIST_FOREACH(list, cur)
- *      printf("\ta=%d, b=%d\n", cur->a, cur->b);
- *
- *    list = eina_inlist_remove(list, EINA_INLIST_GET(d));
- *    free(d);
- *    printf("list=%p\n", list);
- *    for (itr = list; itr != NULL; itr = itr->next)
- *      {
- *         cur = EINA_INLIST_CONTAINER_GET(itr, struct my_struct);
- *         printf("\ta=%d, b=%d\n", cur->a, cur->b);
- *      }
- *
- *    while (list)
- *      {
- *         Eina_Inlist *aux = list;
- *         list = eina_inlist_remove(list, list);
- *         free(aux);
- *      }
- *
- *    eina_shutdown();
- *
- *    return 0;
- * }
- * @endcode
+ * A simple example demonstrating the basic usage of an inlist can be found
+ * here: @ref inlist_01_example_page
+ *
+ * @section inlist_algo Algorithm
+ *
+ * The basic structure can be represented by the following picture:
+ *
+ * @image html eina_inlist-node.png
+ * @image rtf eina_inlist-node.png
+ *
+ * One data structure will also have the node information, with three pointers:
+ * @a prev, @a next and @a last. The @a last pointer is just valid for the first
+ * element (the list head), otherwise each insertion in the list would have to
+ * be done updating every node with the correct pointer. This means that it's
+ * always very important to keep a pointer to the first element of the list,
+ * since it is the only one that has the correct information to allow a proper
+ * O(1) append to the list.
+ *
+ * @section inlist_perf Performance
+ *
+ * Due to the nature of the inlist, there's no accounting information, and no
+ * easy access to the last element from each list node. This means that @ref
+ * eina_inlist_count() is order-N, while @ref eina_list_count() is order-1 (constant
+ * time).
+ *
+ * For the same reasons, @ref eina_inlist_sort() is slower than @ref
+ * eina_list_sort() . If the list is intended to have faster access, be
+ * sorted/merged frequently, or needs to have other complex operations, consider
+ * using @ref Eina_List instead.
+ *
+ * @section inlist_advanced Advanced Usage
+ *
+ * The basic usage considers a struct that will have the user data, and also
+ * have an inlist node information (prev, next and last pointers) created with
+ * @ref EINA_INLIST during the struct declaration. This allows one to use the
+ * convenience macros @ref EINA_INLIST_GET(), @ref EINA_INLIST_CONTAINER_GET(),
+ * @ref EINA_INLIST_FOREACH() and so. This happens because the @ref EINA_INLIST
+ * macro declares a struct member with the name @a __inlist, and all the other
+ * macros assume that this struct member has this name.
+ *
+ * It may be the case that someone needs to have some inlist nodes added to a
+ * @ref Eina_List too. If this happens, the inlist nodes can be added to the
+ * @ref Eina_List without any problems. This example demonstrates this case:
+ * @ref inlist_02_example_page
+ *
+ * It's also possible to have some data that is part of two different inlists.
+ * If this is the case, then it won't be possible to use the convenience macros
+ * to both of the lists. It will be necessary to create a new set of macros that
+ * will allow access to the second list node info. An example for this usage can
+ * be found here:
+ * @ref inlist_03_example_page
+ *
+ * List of examples:
+ * @li @ref inlist_01_example_page
+ * @li @ref inlist_02_example_page
+ * @li @ref inlist_03_example_page
  *
  * @{
  */