1
/*
2
 * Copyright © 2006 Joonas Pihlaja
3
 *
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.
13
 *
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.
21
 */
22
#ifndef CAIRO_FREELIST_H
23
#define CAIRO_FREELIST_H
24

            
25
#include "cairo-types-private.h"
26
#include "cairo-compiler-private.h"
27
#include "cairo-freelist-type-private.h"
28

            
29
/* for stand-alone compilation*/
30
#ifndef VG
31
#define VG(x)
32
#endif
33

            
34
#ifndef NULL
35
#define NULL (void *) 0
36
#endif
37

            
38
/* Initialise a freelist that will be responsible for allocating
39
 * nodes of size nodesize. */
40
cairo_private void
41
_cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize);
42

            
43
/* Deallocate any nodes in the freelist. */
44
cairo_private void
45
_cairo_freelist_fini (cairo_freelist_t *freelist);
46

            
47
/* Allocate a new node from the freelist.  If the freelist contains no
48
 * nodes, a new one will be allocated using malloc().  The caller is
49
 * responsible for calling _cairo_freelist_free() or free() on the
50
 * returned node.  Returns %NULL on memory allocation error. */
51
cairo_private void *
52
_cairo_freelist_alloc (cairo_freelist_t *freelist);
53

            
54
/* Allocate a new node from the freelist.  If the freelist contains no
55
 * nodes, a new one will be allocated using calloc().  The caller is
56
 * responsible for calling _cairo_freelist_free() or free() on the
57
 * returned node.  Returns %NULL on memory allocation error. */
58
cairo_private void *
59
_cairo_freelist_calloc (cairo_freelist_t *freelist);
60

            
61
/* Return a node to the freelist. This does not deallocate the memory,
62
 * but makes it available for later reuse by
63
 * _cairo_freelist_alloc(). */
64
cairo_private void
65
_cairo_freelist_free (cairo_freelist_t *freelist, void *node);
66

            
67

            
68
cairo_private void
69
_cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize);
70

            
71
cairo_private void
72
_cairo_freepool_fini (cairo_freepool_t *freepool);
73

            
74
static inline void
75
5463
_cairo_freepool_reset (cairo_freepool_t *freepool)
76
{
77
6891
    while (freepool->pools != &freepool->embedded_pool) {
78
1428
	cairo_freelist_pool_t *pool = freepool->pools;
79
1428
	freepool->pools = pool->next;
80
1428
	pool->next = freepool->freepools;
81
1428
	freepool->freepools = pool;
82
    }
83

            
84
5463
    freepool->embedded_pool.rem = sizeof (freepool->embedded_data);
85
5463
    freepool->embedded_pool.data = freepool->embedded_data;
86
5463
}
87

            
88
cairo_private void *
89
_cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool);
90

            
91
static inline void *
92
175842
_cairo_freepool_alloc_from_pool (cairo_freepool_t *freepool)
93
{
94
    cairo_freelist_pool_t *pool;
95
    uint8_t *ptr;
96

            
97
175842
    pool = freepool->pools;
98
175842
    if (unlikely (freepool->nodesize > pool->rem))
99
1533
	return _cairo_freepool_alloc_from_new_pool (freepool);
100

            
101
174309
    ptr = pool->data;
102
174309
    pool->data += freepool->nodesize;
103
174309
    pool->rem -= freepool->nodesize;
104
    VG (VALGRIND_MAKE_MEM_UNDEFINED (ptr, freepool->nodesize));
105
174309
    return ptr;
106
}
107

            
108
static inline void *
109
673305
_cairo_freepool_alloc (cairo_freepool_t *freepool)
110
{
111
    cairo_freelist_node_t *node;
112

            
113
673305
    node = freepool->first_free_node;
114
673305
    if (node == NULL)
115
175842
	return _cairo_freepool_alloc_from_pool (freepool);
116

            
117
    VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
118
497463
    freepool->first_free_node = node->next;
119
    VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freepool->nodesize));
120

            
121
497463
    return node;
122
}
123

            
124
cairo_private cairo_status_t
125
_cairo_freepool_alloc_array (cairo_freepool_t *freepool,
126
			     int count,
127
			     void **array);
128

            
129
static inline void
130
519204
_cairo_freepool_free (cairo_freepool_t *freepool, void *ptr)
131
{
132
519204
    cairo_freelist_node_t *node = ptr;
133

            
134
519204
    node->next = freepool->first_free_node;
135
519204
    freepool->first_free_node = node;
136
    VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freepool->nodesize));
137
519204
}
138

            
139
#endif /* CAIRO_FREELIST_H */