* Daniel Juyung Seo <seojuyu...@gmail.com> [2011-06-15 11:29:26 +0900]:
> Awesome! Good job! > We really needed this kind of tutorial. > Thanks glima and gastal. You're welcome. > > Daniel Juyung Seo (SeoZ) > > On Wed, Jun 15, 2011 at 2:43 AM, Enlightenment SVN > <no-re...@enlightenment.org> wrote: > > Log: > > eina: Add detailed description and some examples to Eina_Inlist. > > > > > > > > Author: antognolli > > Date: 2011-06-14 10:43:53 -0700 (Tue, 14 Jun 2011) > > New Revision: 60310 > > Trac: http://trac.enlightenment.org/e/changeset/60310 > > > > Added: > > trunk/eina/doc/img/eina_inlist-node.png > > trunk/eina/doc/img/eina_inlist-node_eg1-inlist.png > > trunk/eina/doc/img/eina_inlist-node_eg1-my-struct.png > > trunk/eina/doc/img/eina_inlist-node_eg2-list-inlist.png > > trunk/eina/doc/img/eina_inlist-node_eg2-my-struct.png > > trunk/eina/doc/img/eina_inlist-node_eg3-my-struct.png > > trunk/eina/doc/img/eina_inlist-node_eg3-two-inlists.png > > trunk/eina/src/examples/eina_inlist_01.c > > trunk/eina/src/examples/eina_inlist_02.c > > trunk/eina/src/examples/eina_inlist_03.c > > Modified: > > trunk/eina/src/examples/Makefile.am trunk/eina/src/include/eina_inlist.h > > > > > > Property changes on: trunk/eina/doc/img/eina_inlist-node.png > > ___________________________________________________________________ > > Added: svn:mime-type > > + application/octet-stream > > > > > > Property changes on: trunk/eina/doc/img/eina_inlist-node_eg1-inlist.png > > ___________________________________________________________________ > > Added: svn:mime-type > > + application/octet-stream > > > > > > Property changes on: trunk/eina/doc/img/eina_inlist-node_eg1-my-struct.png > > ___________________________________________________________________ > > Added: svn:mime-type > > + application/octet-stream > > > > > > Property changes on: trunk/eina/doc/img/eina_inlist-node_eg2-list-inlist.png > > ___________________________________________________________________ > > Added: svn:mime-type > > + application/octet-stream > > > > > > Property changes on: trunk/eina/doc/img/eina_inlist-node_eg2-my-struct.png > > ___________________________________________________________________ > > Added: svn:mime-type > > + application/octet-stream > > > > > > Property changes on: trunk/eina/doc/img/eina_inlist-node_eg3-my-struct.png > > ___________________________________________________________________ > > Added: svn:mime-type > > + application/octet-stream > > > > > > Property changes on: trunk/eina/doc/img/eina_inlist-node_eg3-two-inlists.png > > ___________________________________________________________________ > > Added: svn:mime-type > > + application/octet-stream > > > > Modified: trunk/eina/src/examples/Makefile.am > > =================================================================== > > --- trunk/eina/src/examples/Makefile.am 2011-06-14 16:29:21 UTC (rev 60309) > > +++ trunk/eina/src/examples/Makefile.am 2011-06-14 17:43:53 UTC (rev 60310) > > @@ -20,7 +20,10 @@ > > 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 @@ > > 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 > > > > > > Modified: trunk/eina/src/include/eina_inlist.h > > =================================================================== > > --- trunk/eina/src/include/eina_inlist.h 2011-06-14 16:29:21 UTC > > (rev 60309) > > +++ trunk/eina/src/include/eina_inlist.h 2011-06-14 17:43:53 UTC > > (rev 60310) > > @@ -25,17 +25,275 @@ > > #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. > > * > > @@ -46,62 +304,63 @@ > > * 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> > > + * A simple example demonstrating the basic usage of an inlist can be found > > + * here: @ref inlist_01_example_page > > * > > - * int > > - * main(void) > > - * { > > - * struct my_struct { > > - * EINA_INLIST; > > - * int a, b; > > - * } *d, *cur; > > - * Eina_Inlist *list, *itr; > > + * @section inlist_algo Algorithm > > * > > - * eina_init(); > > + * The basic structure can be represented by the following picture: > > * > > - * d = malloc(sizeof(*d)); > > - * d->a = 1; > > - * d->b = 10; > > - * list = eina_inlist_append(NULL, EINA_INLIST_GET(d)); > > + * @image html eina_inlist-node.png > > + * @image rtf eina_inlist-node.png > > * > > - * d = malloc(sizeof(*d)); > > - * d->a = 2; > > - * d->b = 20; > > - * list = eina_inlist_append(list, EINA_INLIST_GET(d)); > > + * 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. > > * > > - * d = malloc(sizeof(*d)); > > - * d->a = 3; > > - * d->b = 30; > > - * list = eina_inlist_prepend(list, EINA_INLIST_GET(d)); > > + * @section inlist_perf Performance > > * > > - * printf("list=%p\n", list); > > - * EINA_INLIST_FOREACH(list, cur) > > - * printf("\ta=%d, b=%d\n", cur->a, cur->b); > > + * 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). > > * > > - * 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); > > - * } > > + * 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. > > * > > - * while (list) > > - * { > > - * Eina_Inlist *aux = list; > > - * list = eina_inlist_remove(list, list); > > - * free(aux); > > - * } > > + * @section inlist_advanced Advanced Usage > > * > > - * eina_shutdown(); > > + * 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. > > * > > - * return 0; > > - * } > > - * @endcode > > + * 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 > > + * > > * @{ > > */ > > > > > > > > ------------------------------------------------------------------------------ > > EditLive Enterprise is the world's most technically advanced content > > authoring tool. Experience the power of Track Changes, Inline Image > > Editing and ensure content is compliant with Accessibility Checking. > > http://p.sf.net/sfu/ephox-dev2dev > > _______________________________________________ > > enlightenment-svn mailing list > > enlightenment-...@lists.sourceforge.net > > https://lists.sourceforge.net/lists/listinfo/enlightenment-svn > > > > ------------------------------------------------------------------------------ > EditLive Enterprise is the world's most technically advanced content > authoring tool. Experience the power of Track Changes, Inline Image > Editing and ensure content is compliant with Accessibility Checking. > http://p.sf.net/sfu/ephox-dev2dev > _______________________________________________ > enlightenment-devel mailing list > enlightenment-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/enlightenment-devel -- Gustavo Lima Chaves Computer Engineer @ ProFUSION Embedded Systems ------------------------------------------------------------------------------ EditLive Enterprise is the world's most technically advanced content authoring tool. Experience the power of Track Changes, Inline Image Editing and ensure content is compliant with Accessibility Checking. http://p.sf.net/sfu/ephox-dev2dev _______________________________________________ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel