summaryrefslogtreecommitdiff
path: root/ccan/tal/talloc/talloc.h
blob: 8dfb80e7dd27ea59af20a57cf94966e94a589dd9 (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
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
/* Licensed under LGPL - see LICENSE file for details */
#ifndef CCAN_TAL_TALLOC_H
#define CCAN_TAL_TALLOC_H
#include "config.h"
#include <ccan/compiler/compiler.h>
#include <ccan/likely/likely.h>
#include <ccan/typesafe_cb/typesafe_cb.h>
#include <ccan/str/str.h>
#include <talloc.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdarg.h>

/**
 * tal_t - convenient alias for void to mark tal pointers.
 *
 * Since any pointer can be a tal-allocated pointer, it's often
 * useful to use this typedef to mark them explicitly.
 */
typedef TALLOC_CTX tal_t;

/**
 * tal - basic allocator function
 * @ctx: NULL, or tal allocated object to be parent.
 * @type: the type to allocate.
 *
 * Allocates a specific type, with a given parent context.  The name
 * of the object is a string of the type, but if CCAN_TAL_DEBUG is
 * defined it also contains the file and line which allocated it.
 *
 * Example:
 *	int *p = tal(NULL, int);
 *	*p = 1;
 */
#define tal(ctx, type)							\
	((type *)tal_talloc_((ctx), sizeof(type), false,		\
			     TAL_LABEL(type, "")))

/**
 * talz - zeroing allocator function
 * @ctx: NULL, or tal allocated object to be parent.
 * @type: the type to allocate.
 *
 * Equivalent to tal() followed by memset() to zero.
 *
 * Example:
 *	p = talz(NULL, int);
 *	assert(*p == 0);
 */
#define talz(ctx, type)						\
	((type *)tal_talloc_((ctx), sizeof(type), true,		\
			     TAL_LABEL(type, "")))

/**
 * tal_free - free a tal-allocated pointer.
 * @p: NULL, or tal allocated object to free.
 *
 * This calls the destructors for p (if any), then does the same for all its
 * children (recursively) before finally freeing the memory.  It returns
 * NULL, for convenience.
 *
 * Note: errno is preserved by this call.
 *
 * Example:
 *	p = tal_free(p);
 */
#define tal_free(p) tal_talloc_free_(p)

/**
 * tal_arr - allocate an array of objects.
 * @ctx: NULL, or tal allocated object to be parent.
 * @type: the type to allocate.
 * @count: the number to allocate.
 *
 * Note that an object allocated with tal_arr() has a length property;
 * see tal_count().
 *
 * Example:
 *	p = tal_arr(NULL, int, 2);
 *	p[0] = 0;
 *	p[1] = 1;
 */
#define tal_arr(ctx, type, count)					\
	((type *)tal_talloc_arr_((ctx), sizeof(type), (count), false,	\
				 TAL_LABEL(type, "[]")))

/**
 * tal_arrz - allocate an array of zeroed objects.
 * @ctx: NULL, or tal allocated object to be parent.
 * @type: the type to allocate.
 * @count: the number to allocate.
 *
 * Note that an object allocated with tal_arrz() has a length property;
 * see tal_count().
 *
 * Example:
 *	p = tal_arrz(NULL, int, 2);
 *	assert(p[0] == 0 && p[1] == 0);
 */
#define tal_arrz(ctx, type, count) \
	((type *)tal_talloc_arr_((ctx), sizeof(type), (count), true,	\
				 TAL_LABEL(type, "[]")))

/**
 * tal_resize - enlarge or reduce a tal_arr[z].
 * @p: A pointer to the tal allocated array to resize.
 * @count: the number to allocate.
 *
 * This returns true on success (and may move *@p), or false on failure.
 * If @p has a length property, it is updated on success.
 *
 * Example:
 *	tal_resize(&p, 100);
 */
#define tal_resize(p, count) \
	tal_talloc_resize_((void **)(p), sizeof**(p), (count))

/**
 * tal_steal - change the parent of a tal-allocated pointer.
 * @ctx: The new parent.
 * @ptr: The tal allocated object to move.
 *
 * This may need to perform an allocation, in which case it may fail; thus
 * it can return NULL, otherwise returns @ptr.
 */
#define tal_steal(ctx, ptr) talloc_steal((ctx), (ptr))

/**
 * tal_add_destructor - add a callback function when this context is destroyed.
 * @ptr: The tal allocated object.
 * @function: the function to call before it's freed.
 *
 * This is a more convenient form of tal_add_notifier(@ptr,
 * TAL_NOTIFY_FREE, ...), in that the function prototype takes only @ptr.
 */
#define tal_add_destructor(ptr, function)				\
	tal_talloc_add_destructor_((ptr), typesafe_cb(void, void *,	\
						      (function), (ptr)))

/**
 * tal_del_destructor - remove a destructor callback function.
 * @ptr: The tal allocated object.
 * @function: the function to call before it's freed.
 *
 * If @function has not been successfully added as a destructor, this returns
 * false.
 *
 * Note: you can't add more than one destructor with the talloc backend!
 */
#define tal_del_destructor(ptr, function)				      \
	tal_talloc_del_destructor_((ptr), typesafe_cb(void, void *,	\
						      (function), (ptr)))

/**
 * tal_set_name - attach a name to a tal pointer.
 * @ptr: The tal allocated object.
 * @name: The name to use.
 *
 * The name is copied, unless we're certain it's a string literal.
 */
#define tal_set_name(ptr, name)				      \
	tal_talloc_set_name_((ptr), (name), TAL_TALLOC_IS_LITERAL(name))

/**
 * tal_name - get the name for a tal pointer.
 * @ptr: The tal allocated object.
 *
 * Returns NULL if no name has been set.
 */
#define tal_name(ptr) \
	tal_talloc_name_(ptr)

/**
 * tal_count - get the count of objects in a tal_arr.
 * @ptr: The tal allocated object array.
 */
#define tal_count(ptr) talloc_array_length(ptr)

/**
 * tal_parent - get the parent of a tal object.
 * @ctx: The tal allocated object.
 *
 * Returns the parent, which may be NULL.  Returns NULL if @ctx is NULL.
 */
#define tal_parent(ctx) talloc_parent(ctx)

/**
 * tal_dup - duplicate an object.
 * @ctx: The tal allocated object to be parent of the result (may be NULL).
 * @type: the type (should match type of @p!)
 * @p: the object to copy (or reparented if take())
 */
#define tal_dup(ctx, type, p)						\
	((type *)tal_talloc_dup_((ctx), tal_talloc_typechk_(p, type *),	\
				 sizeof(type), 1, 0,			\
				 TAL_LABEL(type, "")))

/**
 * tal_dup_arr - duplicate an array.
 * @ctx: The tal allocated object to be parent of the result (may be NULL).
 * @type: the type (should match type of @p!)
 * @p: the array to copy (or resized & reparented if take())
 * @n: the number of sizeof(type) entries to copy.
 * @extra: the number of extra sizeof(type) entries to allocate.
 */
#define tal_dup_arr(ctx, type, p, n, extra)					\
	((type *)tal_talloc_dup_((ctx), tal_talloc_typechk_(p, type *),	\
				 sizeof(type), (n), (extra),		\
				 TAL_LABEL(type, "[]")))


/**
 * tal_set_backend - set the allocation or error functions to use
 * @alloc_fn: NULL
 * @resize_fn: NULL
 * @free_fn: NULL
 * @error_fn: called on errors or NULL (default is abort)
 *
 * The defaults are set up so tal functions never return NULL, but you
 * can override error_fn to change that.  error_fn can return, and is
 * called if malloc or realloc fail.
 */
#define tal_set_backend(alloc_fn, resize_fn, free_fn, error_fn) \
	tal_talloc_set_backend_((alloc_fn), (resize_fn), (free_fn), (error_fn))

/**
 * tal_expand - expand a tal array with contents.
 * @a1p: a pointer to the tal array to expand.
 * @a2: the second array (can be take()).
 * @num2: the number of elements in the second array.
 *
 * Note that *@a1 and @a2 should be the same type.  tal_count(@a1) will
 * be increased by @num2.
 *
 * Example:
 *	int *arr1 = tal_arrz(NULL, int, 2);
 *	int arr2[2] = { 1, 3 };
 *
 *	tal_expand(&arr1, arr2, 2);
 *	assert(tal_count(arr1) == 4);
 *	assert(arr1[2] == 1);
 *	assert(arr1[3] == 3);
 */
#define tal_expand(a1p, a2, num2)				\
	tal_talloc_expand_((void **)(a1p), (a2), sizeof**(a1p),	\
			   (num2) + 0*sizeof(*(a1p) == (a2)))


/**
 * tal_check - set the allocation or error functions to use
 * @ctx: a tal context, or NULL.
 * @errorstr: a string to prepend calls to error_fn, or NULL.
 *
 * This sanity-checks a tal tree (unless NDEBUG is defined, in which case
 * it simply returns true).  If errorstr is not null, error_fn is called
 * when a problem is found, otherwise it is not.
 */
#define tal_check(ctx, errorstr) \
	tal_talloc_check_((ctx), (errorstr))


/* Internal support functions */
#ifndef TAL_TALLOC_LABEL
#ifdef CCAN_TAL_NO_LABELS
#define TAL_LABEL(type, arr) NULL
#else
#ifdef CCAN_TAL_DEBUG
#define TAL_LABEL(type, arr) \
	__FILE__ ":" stringify(__LINE__) ":" stringify(type) arr
#else
#define TAL_LABEL(type, arr) stringify(type) arr
#endif /* CCAN_TAL_DEBUG */
#endif
#endif

#if HAVE_BUILTIN_CONSTANT_P
#define TAL_TALLOC_IS_LITERAL(str) __builtin_constant_p(str)
#else
#define TAL_TALLOC_IS_LITERAL(str) false
#endif

#if HAVE_TYPEOF && HAVE_STATEMENT_EXPR
/* Careful: ptr can be const foo *, ptype is foo *.  Also, ptr could
 * be an array, eg "hello". */
#define tal_talloc_typechk_(ptr, ptype) ({ __typeof__((ptr)+0) _p = (ptype)(ptr); _p; })
#else
#define tal_talloc_typechk_(ptr, ptype) (ptr)
#endif

void *tal_talloc_(const tal_t *ctx, size_t bytes, bool clear,
		  const char *label);
void *tal_talloc_arr_(const tal_t *ctx, size_t bytes, size_t count, bool clear,
		      const char *label);
void *tal_talloc_free_(const tal_t *ctx);
const char *tal_talloc_name_(const tal_t *ctx);
bool tal_talloc_set_name_(tal_t *ctx, const char *name, bool literal);

bool tal_talloc_add_destructor_(const tal_t *ctx, void (*destroy)(void *me));
bool tal_talloc_del_destructor_(const tal_t *ctx, void (*destroy)(void *me));

/* ccan/tal/str uses this, so define it. */
#define tal_dup_(ctx, p, size, n, extra, add_count, label) \
	tal_talloc_dup_((ctx), (p), (size), (n), (extra), (label))
void *tal_talloc_dup_(const tal_t *ctx, const void *p, size_t size,
		      size_t n, size_t extra, const char *label);

bool tal_talloc_resize_(tal_t **ctxp, size_t size, size_t count);
bool tal_talloc_expand_(tal_t **ctxp, const void *src, size_t size, size_t count);
bool tal_talloc_check_(const tal_t *ctx, const char *errorstr);

void tal_talloc_set_backend_(void *(*alloc_fn)(size_t size),
			     void *(*resize_fn)(void *, size_t size),
			     void (*free_fn)(void *),
			     void (*error_fn)(const char *msg));

#endif /* CCAN_TAL_TALLOC_H */