From d99b7d0220d8bd694c0d997622a7a87eb09c5570 Mon Sep 17 00:00:00 2001 From: Pavel Březina Date: Sun, 6 May 2012 14:34:48 +0200 Subject: doc: Add talloc tutorial. Signed-off-by: Andreas Schneider --- lib/talloc/doc/tutorial_context.dox | 196 ++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 lib/talloc/doc/tutorial_context.dox (limited to 'lib/talloc/doc/tutorial_context.dox') diff --git a/lib/talloc/doc/tutorial_context.dox b/lib/talloc/doc/tutorial_context.dox new file mode 100644 index 0000000000..214131878f --- /dev/null +++ b/lib/talloc/doc/tutorial_context.dox @@ -0,0 +1,196 @@ +/** +@page libtalloc_context Chapter 1: Talloc context +@section context Talloc context + +The talloc context is the most important part of this library for it is +responsible for every single feature of this memory allocator. It is a logical +unit which represents a memory space managed by talloc. + +From the programmer's point of view, the talloc context is completely +equivalent to a pointer that would be returned by the memory routines from the +C standard library. This means that every context that is returned from the +talloc library can be used directly in functions that do not use talloc +internally. For example we can do the following: + +@code +char *str1 = strdup("I am NOT a talloc context"); +char *str2 = talloc_strdup(NULL, "I AM a talloc context"); + +printf("%d\n", strcmp(str1, str2) == 0); + +free(str1); +talloc_free(str2); /* we can not use free(str2) */ +@endcode + +This is possible because the context is internally handled as a special +fixed-length structure called talloc chunk. Each chunk stores context metadata +followed by the memory space requested by the programmer. When a talloc +function returns a context (pointer), it in fact returns a pointer to the user +space portion of the talloc chunk. And when we want to manipulate with this +context using talloc functions, the talloc library transforms the user-space +pointer back to the starting address of the chunk. This is also the reason why +we were unable to use free(str2) in the previous example - because +str2 does not point at the beginning of the allocated block of +memory. This is illustrated on the next image: + +@image html context.png + +The type TALLOC_CTX is defined in talloc.h to identify a talloc context in +function parameters. However, this type is just an alias for void +and exists only for semantical reasons - thus we can differentiate between +void* (arbitrary data) and TALLOC_CTX* (talloc context). + +@subsection metadata Context meta data +Every talloc context carries several pieces of internal information along with +the allocated memory: + + - name - which is used in reports of context hierarchy and to simulate + a dynamic type system, + - size of the requested memory in bytes - this can be used to determine + the number of elements in arrays, + - attached destructor - which is executed just before the memory block is + about to be freed, + - references to the context + - children and parent contexts - create the hierarchical view on the + memory. + +@section context-hierarchy Hierarchy of talloc context + +Every talloc context contains information about its parent and children. Talloc +uses this information to create a hierarchical model of memory or to be more +precise, it creates an n-ary tree where each node represents a single talloc +context. The root node of the tree is referred to as a top level context - a +context without any parent. + +This approach has several advantages: + + - as a consequence of freeing a talloc context, all of its children + will be properly deallocated as well, + - the parent of a context can be changed at any time, which + results in moving the whole subtree under another node, + - it creates a more natural way of managing data structures. + +@subsection Example + +We have a structure that stores basic information about a user - his/her name, +identification number and groups he/she is a member of: + +@code +struct user { + uid_t uid; + char *username; + size_t num_groups; + char **groups; +}; +@endcode + +We will allocate this structure using talloc. The result will be the following +context tree: + +@image html context_tree.png + +@code +/* create new top level context */ +struct user *user = talloc(NULL, struct user); + +user->uid = 1000; +user->num_groups = N; + +/* make user the parent of following contexts */ +user->username = talloc_strdup(user, "Test user"); +user->groups = talloc_array(user, char*, user->num_groups); + +for (i = 0; i < user->num_groups; i++) { + /* make user->groups the parent of following context */ + user->groups[i] = talloc_asprintf(user->groups, + "Test group %d", i); +} +@endcode + +This way, we have gained a lot of additional capabilities, one of which is +very simple deallocation of the structure and all of its elements. + +With the C standard library we need first to iterate over the array of groups +and free every element separately. Then we must deallocate the array that stores +them. Next we deallocate the username and as the last step free the structure +itself. But with talloc, the only operation we need to execute is freeing the +structure context. Its descendants will be freed automatically. + +@code +talloc_free(user); +@endcode + +@section keep-hierarchy Always keep the hieararchy steady! + +The talloc is a hierarchy memory allocator. The hierarchy nature is what makes +the programming more error proof. It makes the memory easier to manage and free. +Therefore, the first thing we should have on our mind is: always project +our data structures into the talloc context hierarchy. + +That means if we have a structure, we should always use it as a parent context +for its elements. This way we will not encounter any troubles when freeing this +structure or when changing its parent. The same rule applies for arrays. + +@section creating-context Creating a talloc context + +Here are the most important functions that creates a new talloc context. + +@subsection type-safe Type-safe functions + +It allocates the size that is necessary for the this type and returns a +new, properly-cast pointer. This is the preferred way to create a new context +as we can rely on the compiler to detect type mismatches. + +They automatically set the name of the context to the name of the data type. +Which is used to simulate the dynamic type system. + +@code +struct user *user = talloc(ctx, struct user); + +/* initialize to default values */ +user->uid = 0; +user->name = NULL; +user->num_groups = 0; +user->groups = NULL; + +/* or we can achieve the same result with */ +struct user *user_zero = talloc_zero(ctx, struct user); +@endcode + +@subsection zero-length Zero-lenght contexts + +The zero-length context is basically a context without any special semantical +meaning. We can use it the same way as any other context. The only difference +is that it consists only of the meta data about the context. Therefore, it is +strictly of type |TALLOC_CTX*|. It is often used in cases where we want to +aggregate several data structures under one parent (zero-length) context, such +as a temporary context to contain memory needed within a single function that +is not interesting to the caller. Allocating on a zero-length temporary context +will make clean-up of the function simpler. + +@code +TALLOC_CTX *ctx = NULL; +struct foo *foo = NULL; +struct bar *bar = NULL; + +/* new zero-length top level context */ +ctx = talloc_new(NULL); +if (ctx == NULL) { + return ENOMEM; +} + +foo = talloc(ctx, struct foo); +bar = talloc(ctx, struct bar); + +/* free everything at once */ +talloc_free(ctx); +@endcode + +@subsection context-see-also See also + +- talloc_size() +- talloc_named() +- @ref talloc_array +- @ref talloc_string + +*/ \ No newline at end of file -- cgit