efl
206 строк · 4.5 Кб
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include <stdlib.h>
6#include <string.h>
7
8#include "Evas_Data.h"
9#include "evas_mempool.h"
10
11#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
12# define UNUSED __attribute__ ((__unused__))
13#else
14# define UNUSED
15#endif
16
17//#define NOPOOL
18
19typedef struct _Pool Pool;
20
21struct _Pool
22{
23int usage;
24void *base;
25Pool *prev, *next;
26};
27
28
29Pool *
30_evas_mp_pool_new(Evas_Mempool *pool)
31{
32#ifdef NOPOOL
33static Pool thepool;
34return &thepool;
35#else
36Pool *p;
37void **ptr;
38int item_alloc, i;
39
40item_alloc =
41((pool->item_size + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *);
42p = malloc(sizeof(Pool) + (pool->pool_size * item_alloc));
43if (!p) return NULL;
44ptr = (void **)(((unsigned char *)p) + sizeof(Pool));
45p->usage = 0;
46p->base = ptr;
47for (i = 0; i < pool->pool_size - 1; i++)
48{
49*ptr = (void **)(((unsigned char *)ptr) + item_alloc);
50ptr = *ptr;
51}
52*ptr = NULL;
53return p;
54#endif
55}
56
57void
58_evas_mp_pool_free(Pool *p)
59{
60#if !defined(NOPOOL)
61free(p);
62#endif
63}
64
65void *
66evas_mempool_malloc(Evas_Mempool *pool, int size UNUSED)
67{
68#ifdef NOPOOL
69return malloc(size);
70#else
71Pool *p;
72void *mem;
73
74for (p = pool->first; p; p = p->next) // look 4 pool from 2nd bucket on
75{
76if (p->base) // base is not NULL - has a free slot
77{
78if (p->prev)
79{
80if (pool->last == p)
81pool->last = p->prev;
82
83p->prev->next = p->next;
84p->prev = NULL;
85p->next = pool->first;
86p->next->prev = p;
87pool->first = p;
88}
89
90break;
91}
92}
93if (!p) // we have reached the end of the list - no free pools
94{
95p = _evas_mp_pool_new(pool);
96if (!p)
97return NULL;
98
99p->prev = NULL;
100p->next = pool->first;
101if (p->next)
102p->next->prev = p;
103
104if (!pool->last)
105pool->last = p;
106
107pool->first = p;
108}
109
110mem = p->base; // this points to the next free block - so take it
111p->base = *((void **)mem); // base now points to the next free block
112if (!p->base) // move to end - it just filled up
113if (p->next)
114{
115if (p->prev)
116p->prev->next = p->next;
117else
118pool->first = p->next;
119
120p->next->prev = p->prev;
121((Pool *)pool->last)->next = p;
122p->prev = pool->last;
123p->next = NULL;
124pool->last = p;
125}
126
127p->usage++;
128pool->usage++;
129return mem;
130#endif
131}
132
133void
134evas_mempool_free(Evas_Mempool *pool, void *ptr)
135{
136#ifdef NOPOOL
137free(ptr);
138#else
139Pool *p;
140void *pmem;
141int item_alloc, psize;
142
143item_alloc =
144((pool->item_size + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *);
145psize = item_alloc * pool->pool_size;
146for (p = (Pool *)(pool->first); p; p = p->next) // look 4 pool
147{
148pmem = (void *)(((unsigned char *)p) + sizeof(Pool)); // pool mem base
149if ((ptr >= pmem) &&
150((unsigned char *)ptr < (((unsigned char *)pmem) + psize))) // is it in pool mem?
151{
152*((void **)ptr) = p->base; // freed node points to prev free node
153p->base = ptr; // next free node is now the one we freed
154p->usage--;
155pool->usage--;
156if (p->usage == 0) // free bucket
157{
158if (p->prev)
159p->prev->next = p->next;
160
161if (p->next)
162p->next->prev = p->prev;
163
164if (pool->last == p)
165pool->last = p->prev;
166
167if (pool->first == p)
168pool->first = p->next;
169
170_evas_mp_pool_free(p);
171}
172else if (p->prev) // if not the first - move to front
173{
174p->prev->next = p->next;
175if (p->next)
176p->next->prev = p->prev;
177
178if (pool->last == p)
179pool->last = p->prev;
180
181p->prev = NULL;
182p->next = pool->first;
183p->next->prev = p;
184pool->first = p;
185}
186
187break;
188}
189}
190#endif
191}
192
193
194void *
195evas_mempool_calloc(Evas_Mempool *pool, int size)
196{
197#ifdef NOPOOL
198return calloc(1, size);
199#else
200void *mem;
201
202mem = evas_mempool_malloc(pool, size);
203memset(mem, 0, size);
204return mem;
205#endif
206}
207
208