[go: up one dir, main page]

File: autod.h

package info (click to toggle)
aewan 1.0.01-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 816 kB
  • sloc: ansic: 4,439; python: 122; makefile: 67; sh: 14
file content (122 lines) | stat: -rw-r--r-- 4,528 bytes parent folder | download | duplicates (8)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
LICENSE INFORMATION:
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
Copyright (c) 2002 Bruno T. C. de Oliveira

INFORMAES DE LICENA:
Este programa  um software de livre distribuio; voc pode
redistribu-lo e/ou modific-lo sob os termos da GNU General
Public License, conforme publicado pela Free Software Foundation,
pela verso 2 da licena ou qualquer verso posterior.

Este programa  distribudo na esperana de que ele ser til
aos seus usurios, porm, SEM QUAISQUER GARANTIAS; sem sequer
a garantia implcita de COMERCIABILIDADE ou DE ADEQUAO A
QUALQUER FINALIDADE ESPECFICA. Consulte a GNU General Public
License para obter mais detalhes (uma cpia acompanha este
programa, armazenada no arquivo COPYING).
*/

/* This is a set of convenience macros and functions for enabling
 * "automatic" destruction of dynamically-allocated objects when
 * exitting the scope of a function. This is especially useful
 * in functions that can return at several points, and it would be
 * difficult to keep track of what is allocated at which point in order
 * to free everything correctly. 
 *
 * The philosophy is this:
 *
 * void my_func(...) {
 *    Brick *my_brick;
 *    Camel *my_camel;
 *    char *my_string;
 *
 *    autod_begin;
 *    autod_register(my_brick, brick_destroy);  // also sets my_brick = NULL
 *    autod_register(my_camel, camel_destroy);  // also sets my_camel = NULL
 *    autod_register(my_string, free);          // also sets my_string = NULL
 *
 *    // do what you want with my_brick, my_camel and my_string
 *
 *    if (somefunc() == ERROR)
 *       autod_return;  // this takes care of destroying my_brick,
 *                      // my_camel and my_string, by calling the
 *                      // destructor function specified when registering
 *
 *    // do more stuff with my_brick, my_camel, my_string
 *
 *    autod_return;  // don't forget to put this at the end
 * }
 *
 * Sometimes you will want to return a registered object, which means
 * that it should not be free'd (the caller will get ownership of the
 * object). In this case, use autod_return_obj(v), and all registered
 * pointers will be free'd except v, which will be returned.
 *
 * Also, notice you should never do:
 *
 *      my_camel = other_camel;
 *
 * Because the original value of my_camel will be lost and will not
 * be free'd (memory leak). Instead, you should do:
 *
 *      if (my_camel) camel_destroy(my_camel);
 *      my_camel = other_camel;
 *
 * Since this occurs often, a convenience macro is provided:
 *
 *      autod_assign(my_camel, other_camel);
 *
 * This takes care of destroying the old camel before assigning the new one
 * (this sentence really sounds weird).
 */


#ifndef btco_bores_autod_h
#define btco_bores_autod_h

#include <stdlib.h>

typedef void (*autod_destructor_t)(void*);

typedef struct AutodRegistryNode_ {
   void **ptr;
   autod_destructor_t destructor;
   struct AutodRegistryNode_ *next;
} AutodRegistryNode;

#define autod_begin  AutodRegistryNode autodregistry_head; \
                     autodregistry_head.next = 0

#define autod_register(ptr, d) do_autod_register(&autodregistry_head, \
                                     (void**)&ptr, (autod_destructor_t)d)

#define autod_return_value(v) { do_autod_cleanup(&autodregistry_head, 0); return v; }
#define autod_return_obj(v) { do_autod_cleanup(&autodregistry_head, (void*)v); return v; }
#define autod_return { do_autod_cleanup(&autodregistry_head, 0); return; }
#define autod_assign(ptr, newvalue) do_autod_assign(&autodregistry_head, \
                                      (void**)&ptr, newvalue)

void do_autod_register(AutodRegistryNode *head, void **ptr, 
                                        autod_destructor_t destr);

void do_autod_assign(AutodRegistryNode *head, void **ptr, void *newvalue);

void do_autod_cleanup(AutodRegistryNode *head, void *ignore_ptr);


#endif