summaryrefslogtreecommitdiffstats
path: root/doc/tutorial_destructors.dox
blob: ed063876a30257b967be793f6c46c2938c54d3cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/**
@page libtalloc_destructors Chapter 4: Using destructors

@section destructors Using destructors

Destructors are well known methods in the world of object oriented programming.
A destructor is a method of an object that is automatically run when the object
is destroyed. It is usually used to return resources taken by the object back to
the system (e.g. closing file descriptors, terminating connection to a database,
deallocating memory).

With talloc we can take the advantage of destructors even in C. We can easily
attach our own destructor to a talloc context. When the context is freed, the
destructor will run automatically.

To attach/detach a destructor to a talloc context use: talloc_set_destructor().

@section destructors-example Example

Imagine that we have a dynamically created linked list. Before we deallocate an
element of the list, we need to make sure that we have successfully removed it
from the list. Normally, this would be done by two commands in the exact order:
remove it from the list and then free the element. With talloc, we can do this
at once by setting a destructor on the element which will remove it from the
list and talloc_free() will do the rest.

The destructor would be:

@code
int list_remove(void *ctx)
{
    struct list_el *el = NULL;
    el = talloc_get_type_abort(ctx, struct list_el);
    /* remove element from the list */
}
@endcode

GCC version 3 and newer can check for the types during the compilation. So if
it is our major compiler, we can use a more advanced destructor:

@code
int list_remove(struct list_el *el)
{
    /* remove element from the list */
}
@endcode

Now we will assign the destructor to the list element. We can do this directly
in the function that inserts it.

@code
struct list_el* list_insert(TALLOC_CTX *mem_ctx,
                            struct list_el *where,
                            void *ptr)
{
  struct list_el *el = talloc(mem_ctx, struct list_el);
  el->data = ptr;
  /* insert into list */

  talloc_set_destructor(el, list_remove);
  return el;
}
@endcode

Because talloc is a hierarchical memory allocator, we can go a step further and
free the data with the element as well:

@code
struct list_el* list_insert_free(TALLOC_CTX *mem_ctx,
                                 struct list_el *where,
                                 void *ptr)
{
  struct list_el *el = NULL;
  el = list_insert(mem_ctx, where, ptr);

  talloc_steal(el, ptr);

  return el;
}
@endcode

*/