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