beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-freelist.c
blobd596eab81dcb68e5997c9e9c68769158c588e26b
1 /*
2 * Copyright © 2006 Joonas Pihlaja
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
23 #include "cairoint.h"
25 #include "cairo-error-private.h"
26 #include "cairo-freelist-private.h"
28 void
29 _cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize)
31 memset (freelist, 0, sizeof (cairo_freelist_t));
32 freelist->nodesize = nodesize;
35 void
36 _cairo_freelist_fini (cairo_freelist_t *freelist)
38 cairo_freelist_node_t *node = freelist->first_free_node;
39 while (node) {
40 cairo_freelist_node_t *next;
42 VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
43 next = node->next;
45 free (node);
46 node = next;
50 void *
51 _cairo_freelist_alloc (cairo_freelist_t *freelist)
53 if (freelist->first_free_node) {
54 cairo_freelist_node_t *node;
56 node = freelist->first_free_node;
57 VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
58 freelist->first_free_node = node->next;
59 VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freelist->nodesize));
61 return node;
64 return malloc (freelist->nodesize);
67 void *
68 _cairo_freelist_calloc (cairo_freelist_t *freelist)
70 void *node = _cairo_freelist_alloc (freelist);
71 if (node)
72 memset (node, 0, freelist->nodesize);
73 return node;
76 void
77 _cairo_freelist_free (cairo_freelist_t *freelist, void *voidnode)
79 cairo_freelist_node_t *node = voidnode;
80 if (node) {
81 node->next = freelist->first_free_node;
82 freelist->first_free_node = node;
83 VG (VALGRIND_MAKE_MEM_NOACCESS (node, freelist->nodesize));
87 void
88 _cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize)
90 freepool->first_free_node = NULL;
91 freepool->pools = &freepool->embedded_pool;
92 freepool->freepools = NULL;
93 freepool->nodesize = nodesize;
95 freepool->embedded_pool.next = NULL;
96 freepool->embedded_pool.size = sizeof (freepool->embedded_data);
97 freepool->embedded_pool.rem = sizeof (freepool->embedded_data);
98 freepool->embedded_pool.data = freepool->embedded_data;
100 VG (VALGRIND_MAKE_MEM_NOACCESS (freepool->embedded_data, sizeof (freepool->embedded_data)));
103 void
104 _cairo_freepool_fini (cairo_freepool_t *freepool)
106 cairo_freelist_pool_t *pool;
108 pool = freepool->pools;
109 while (pool != &freepool->embedded_pool) {
110 cairo_freelist_pool_t *next = pool->next;
111 free (pool);
112 pool = next;
115 pool = freepool->freepools;
116 while (pool != NULL) {
117 cairo_freelist_pool_t *next = pool->next;
118 free (pool);
119 pool = next;
122 VG (VALGRIND_MAKE_MEM_NOACCESS (freepool, sizeof (freepool)));
125 void *
126 _cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool)
128 cairo_freelist_pool_t *pool;
129 int poolsize;
131 if (freepool->freepools != NULL) {
132 pool = freepool->freepools;
133 freepool->freepools = pool->next;
135 poolsize = pool->size;
136 } else {
137 if (freepool->pools != &freepool->embedded_pool)
138 poolsize = 2 * freepool->pools->size;
139 else
140 poolsize = (128 * freepool->nodesize + 8191) & -8192;
142 pool = malloc (sizeof (cairo_freelist_pool_t) + poolsize);
143 if (unlikely (pool == NULL))
144 return pool;
146 pool->size = poolsize;
149 pool->next = freepool->pools;
150 freepool->pools = pool;
152 pool->rem = poolsize - freepool->nodesize;
153 pool->data = (uint8_t *) (pool + 1) + freepool->nodesize;
155 VG (VALGRIND_MAKE_MEM_NOACCESS (pool->data, pool->rem));
157 return pool + 1;
160 cairo_status_t
161 _cairo_freepool_alloc_array (cairo_freepool_t *freepool,
162 int count,
163 void **array)
165 int i;
167 for (i = 0; i < count; i++) {
168 cairo_freelist_node_t *node;
170 node = freepool->first_free_node;
171 if (likely (node != NULL)) {
172 VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
173 freepool->first_free_node = node->next;
174 VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freepool->nodesize));
175 } else {
176 node = _cairo_freepool_alloc_from_pool (freepool);
177 if (unlikely (node == NULL))
178 goto CLEANUP;
181 array[i] = node;
184 return CAIRO_STATUS_SUCCESS;
186 CLEANUP:
187 while (i--)
188 _cairo_freepool_free (freepool, array[i]);
190 return _cairo_error (CAIRO_STATUS_NO_MEMORY);