summaryrefslogtreecommitdiff
path: root/src/cairo-tg-allocator-private.h
blob: f62b2e21181c43e2c42f4464e3f3635636922b0d (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
#ifndef CAIRO_TG_ALLOCATOR_H
#define CAIRO_TG_ALLOCATOR_H

#include "cairoint.h"

typedef struct _cairo_tg_mem_chunk cairo_tg_mem_chunk_t;

struct _cairo_tg_mem_chunk
{
    cairo_tg_mem_chunk_t    *next;
    uint8_t		    *buffer;
    int			    chunk_size;
    int			    remaining_size;
};

typedef struct _cairo_tg_mono_allocator
{
   cairo_tg_mem_chunk_t	    *chunk_head;
   int			    chunk_size;
} cairo_tg_mono_allocator_t;

static inline cairo_tg_mem_chunk_t *
_cairo_tg_mem_chunk_create (int chunk_size)
{
    cairo_tg_mem_chunk_t *chunk;

    chunk = (cairo_tg_mem_chunk_t *) malloc (sizeof (cairo_tg_mem_chunk_t) + chunk_size);

    if (chunk)
    {
	chunk->next = NULL;
	chunk->buffer = (uint8_t *) chunk + sizeof (cairo_tg_mem_chunk_t);
	chunk->chunk_size = chunk_size;
	chunk->remaining_size = chunk_size;
    }

    return chunk;
}

static inline void
_cairo_tg_mem_chunk_destroy (cairo_tg_mem_chunk_t *chunk)
{
    free (chunk);
}

static inline cairo_status_t
_cairo_tg_mono_allocator_init (cairo_tg_mono_allocator_t *allocator, int chunk_size)
{
    cairo_tg_mem_chunk_t *chunk;

    chunk = _cairo_tg_mem_chunk_create (chunk_size);

    if (! chunk)
	return CAIRO_STATUS_NO_MEMORY;

    allocator->chunk_size = chunk_size;
    allocator->chunk_head = chunk;

    return CAIRO_STATUS_SUCCESS;
}

static inline void
_cairo_tg_mono_allocator_fini (cairo_tg_mono_allocator_t *allocator)
{
    cairo_tg_mem_chunk_t *chunk = allocator->chunk_head, *next;

    while (chunk != NULL)
    {
	next = chunk->next;
	_cairo_tg_mem_chunk_destroy (chunk);
	chunk = next;
    }

    allocator->chunk_head = NULL;
}

static inline void *
_cairo_tg_mono_allocator_alloc (cairo_tg_mono_allocator_t *allocator, int size)
{
    cairo_tg_mem_chunk_t *chunk = allocator->chunk_head;
    int chunk_size;

    if (chunk && chunk->remaining_size >= size)
    {
	void *buffer = (void*)(chunk->buffer + chunk->chunk_size - chunk->remaining_size);
	chunk->remaining_size -= size;
	return buffer;
    }

    chunk_size = MAX (allocator->chunk_size, size);

    chunk = _cairo_tg_mem_chunk_create (chunk_size);

    if (chunk == NULL)
	return NULL;

    chunk->next = allocator->chunk_head;
    chunk->buffer = (uint8_t *) chunk + sizeof (cairo_tg_mem_chunk_t);
    chunk->chunk_size = chunk_size;
    chunk->remaining_size = chunk_size - size;

    allocator->chunk_head = chunk;

    return (void *) chunk->buffer;
}

static inline void
_cairo_tg_mono_allocator_reset (cairo_tg_mono_allocator_t *allocator)
{
    cairo_tg_mem_chunk_t *chunk = allocator->chunk_head, *next;
    cairo_tg_mem_chunk_t *stock = NULL;

    while (chunk != NULL)
    {
	next = chunk->next;

	if (stock)
	    _cairo_tg_mem_chunk_destroy (chunk);
	else
	    stock = chunk;

	chunk = next;
    }

    if (stock)
    {
	stock->next = NULL;
	stock->remaining_size = stock->chunk_size;
    }

    allocator->chunk_head = stock;
}

#endif /* CAIRO_TG_ALLOCATOR_H */