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