1 /*
2  * Copyright (c) 2007-2009  Marko Kreen, Skype Technologies OÜ
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  * @file
19  *
20  * Context-based Memory Allocator.
21  *
22  * The idea is that each data structure is given a context to allocate from,
23  * and it can create subcontext for that which can be specific allocation
24  * pattern that matches the data structure.
25  *
26  * It is slightly more work to use than palloc (PostgreSQL) or talloc (Samba),
27  * but it avoids the need to have big fully-featured framework that does
28  * everything at once.
29  *
30  * Instead you have small task-specific allocators, and you can always fall
31  * back to raw malloc if you want to valgrind the code.
32  *
33  * Potential variants:
34  * - fully-featured pooled
35  * - randomly failing
36  * - logging
37  * - locking
38  * - guard signatures
39  * - palloc / talloc like API
40  */
41 
42 #ifndef _USUAL_CXALLOC_H_
43 #define _USUAL_CXALLOC_H_
44 
45 #include <usual/base.h>
46 
47 /**
48  * Ops for allocator that takes context.
49  *
50  * NB! - they are not equivalent to cx_* API.  The cx_*
51  * functions do additional sanitizing.
52  */
53 struct CxOps {
54 	/**
55 	 * Allocate memory.
56 	 * len will not be 0.
57 	 */
58 	void *(*c_alloc)(void *ctx, size_t len);
59 	/**
60 	 * Resize existing allocation.
61 	 * Both p and len will not be 0
62 	 */
63 	void *(*c_realloc)(void *ctx, void *p, size_t len);
64 	/**
65 	 * Free existing allocation.
66 	 * p will not be 0
67 	 */
68 	void (*c_free)(void *ctx, void *p);
69 	/**
70 	 * Release all memory in context.
71 	 * This is not supported by all allocators.
72 	 */
73 	void (*c_destroy)(void *ctx);
74 };
75 
76 /**
77  * Memory allocation context.
78  */
79 struct CxMem {
80 	const struct CxOps *ops;
81 	void *ctx;
82 };
83 
84 /** Shortcut to const CxMem */
85 typedef const struct CxMem CxMem;
86 
87 /*
88  * Basic operations on allocation context.
89  */
90 
91 /**
92  * Allocate memory from context.
93  *
94  * Returns NULL if no memory or len == 0.
95  */
96 void *cx_alloc(CxMem *cx, size_t len) _MALLOC;
97 
98 /**
99  * Change existing allocation.
100  *
101  * If ptr is NULL it creates new allocation.
102  * If len is 0 it frees the memory.
103  */
104 void *cx_realloc(CxMem *cx, void *ptr, size_t len);
105 
106 /**
107  * Free existing allocation.
108  *
109  * Does nothing if ptr is NULL.
110  */
111 void cx_free(CxMem *cx, void *ptr);
112 
113 /**
114  * Release all memory allocated in context.
115  *
116  * Should be called only on contexts that support it.
117  */
118 void cx_destroy(CxMem *cx);
119 
120 /** Allocate and zero-fill memory */
121 void *cx_alloc0(CxMem *cx, size_t len) _MALLOC;
122 
123 /** Allocate and copy */
124 void *cx_memdup(CxMem *cx, const void *src, size_t len) _MALLOC;
125 
126 /** Allocate and copy string */
127 void *cx_strdup(CxMem *cx, const char *str) _MALLOC;
128 
129 /** Print to allocated string, return length or -1 on error. */
130 int cx_asprintf(CxMem *cx, char **dst_p, const char *fmt, ...) _PRINTF(3, 4);
131 
132 /** Print to allocated string, return length or -1 on error */
133 int cx_vasprintf(CxMem *cx, char **dst_p, const char *fmt, va_list ap) _PRINTF(3, 0);
134 
135 /** Print to allocated string, return new string or NULL on error */
136 char *cx_sprintf(CxMem *cx, const char *fmt, ...) _PRINTF(2, 3);
137 
138 /** Print to allocated string, return new string or NULL on error */
139 char *cx_vsprintf(CxMem *cx, const char *fmt, va_list ap) _PRINTF(2, 0);
140 
141 
142 /** Allocator that uses libc malloc/realloc/free */
143 extern CxMem cx_libc_allocator;
144 
145 /** Default allocator */
146 #ifndef USUAL_ALLOC
147 #define USUAL_ALLOC (&cx_libc_allocator)
148 #endif
149 
150 #endif
151