EFL 1.7 svn doobies
[profile/ivi/eina.git] / src / lib / eina_mempool.c
1 /* EINA - EFL data type library
2  * Copyright (C) 2007-2008 Jorge Luis Zapata Muga
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library;
16  * if not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include <assert.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #include "eina_config.h"
29 #include "eina_private.h"
30 #include "eina_hash.h"
31 #include "eina_module.h"
32 #include "eina_log.h"
33 #include "eina_main.h"
34
35 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
36 #include "eina_safety_checks.h"
37 #include "eina_mempool.h"
38
39 /*============================================================================*
40 *                                  Local                                     *
41 *============================================================================*/
42
43 /**
44  * @cond LOCAL
45  */
46
47 static Eina_Hash *_backends;
48 static Eina_Array *_modules;
49 static int _eina_mempool_log_dom = -1;
50
51 #ifdef ERR
52 #undef ERR
53 #endif
54 #define ERR(...) EINA_LOG_DOM_ERR(_eina_mempool_log_dom, __VA_ARGS__)
55
56 #ifdef DBG
57 #undef DBG
58 #endif
59 #define DBG(...) EINA_LOG_DOM_DBG(_eina_mempool_log_dom, __VA_ARGS__)
60
61
62 static Eina_Mempool *
63 _new_va(const char *name,
64         const char *context,
65         const char *options,
66         va_list args)
67 {
68    Eina_Mempool_Backend *be = NULL;
69    Eina_Mempool *mp;
70
71    Eina_Error err = EINA_ERROR_NOT_MEMPOOL_MODULE;
72
73    eina_error_set(0);
74    if (getenv("EINA_MEMPOOL_PASS"))
75      {
76         be = eina_hash_find(_backends, "pass_through");
77         if (!be) be = eina_hash_find(_backends, name);
78      }
79    else be = eina_hash_find(_backends, name);
80    if ((!be) || (!be->init)) goto on_error;
81
82    err = EINA_ERROR_OUT_OF_MEMORY;
83    mp = calloc(1, sizeof(Eina_Mempool));
84    if (!mp)
85       goto on_error;
86
87    /* Work around ABI incompability introduced in Eina 1.1 */
88 #define SBP(Property) mp->backend.Property = be->Property;
89    SBP(name);
90    SBP(init);
91    SBP(free);
92    SBP(alloc);
93    SBP(realloc);
94    SBP(garbage_collect);
95    SBP(statistics);
96    SBP(shutdown);
97 #undef SBP
98
99    if (be->repack)
100      {
101         mp->backend2 = calloc(1, sizeof (Eina_Mempool_Backend_ABI2));
102         if (mp->backend2)
103           mp->backend2->repack = be->repack;
104      }
105
106    mp->backend_data = mp->backend.init(context, options, args);
107
108    return mp;
109
110 on_error:
111    eina_error_set(err);
112    return NULL;
113 }
114
115 /* Built-in backend's prototypes */
116
117 #ifdef EINA_STATIC_BUILD_BUDDY
118 Eina_Bool buddy_init(void);
119 void      buddy_shutdown(void);
120 #endif
121
122 #ifdef EINA_STATIC_BUILD_CHAINED_POOL
123 Eina_Bool chained_init(void);
124 void      chained_shutdown(void);
125 #endif
126
127 #ifdef EINA_STATIC_BUILD_EMEMOA_FIXED
128 Eina_Bool ememoa_fixed_init(void);
129 void      ememoa_fixed_shutdown(void);
130 #endif
131
132 #ifdef EINA_STATIC_BUILD_EMEMOA_UNKNOWN
133 Eina_Bool ememoa_unknown_init(void);
134 void      ememoa_unknown_shutdown(void);
135 #endif
136
137 #ifdef EINA_STATIC_BUILD_FIXED_BITMAP
138 Eina_Bool fixed_bitmap_init(void);
139 void      fixed_bitmap_shutdown(void);
140 #endif
141
142 #ifdef EINA_STATIC_BUILD_ONE_BIG
143 Eina_Bool one_big_init(void);
144 void      one_big_shutdown(void);
145 #endif
146
147 #ifdef EINA_STATIC_BUILD_PASS_THROUGH
148 Eina_Bool pass_through_init(void);
149 void      pass_through_shutdown(void);
150 #endif
151
152 /**
153  * @endcond
154  */
155
156 /*============================================================================*
157 *                                 Global                                     *
158 *============================================================================*/
159
160 /**
161  * @cond LOCAL
162  */
163
164 EAPI Eina_Error EINA_ERROR_NOT_MEMPOOL_MODULE = 0;
165
166 static const char EINA_ERROR_NOT_MEMPOOL_MODULE_STR[] =
167    "Not a memory pool module.";
168
169 /**
170  * @endcond
171  */
172
173 EAPI Eina_Bool
174 eina_mempool_register(Eina_Mempool_Backend *be)
175 {
176    EINA_SAFETY_ON_NULL_RETURN_VAL(be, 0);
177    DBG("be=%p, name=%p", be, be->name);
178    return eina_hash_add(_backends, be->name, be);
179 }
180
181 EAPI void
182 eina_mempool_unregister(Eina_Mempool_Backend *be)
183 {
184    EINA_SAFETY_ON_NULL_RETURN(be);
185    DBG("be=%p, name=%p", be, be->name);
186    eina_hash_del(_backends, be->name, be);
187 }
188
189 Eina_Bool
190 eina_mempool_init(void)
191 {
192    char *path;
193
194    _eina_mempool_log_dom = eina_log_domain_register("eina_mempool",
195                                                     EINA_LOG_COLOR_DEFAULT);
196    if (_eina_mempool_log_dom < 0)
197      {
198         EINA_LOG_ERR("Could not register log domain: eina_mempool");
199         return 0;
200      }
201
202    EINA_ERROR_NOT_MEMPOOL_MODULE = eina_error_msg_static_register(
203          EINA_ERROR_NOT_MEMPOOL_MODULE_STR);
204    _backends = eina_hash_string_superfast_new(NULL);
205
206    /* dynamic backends */
207    _modules = eina_module_arch_list_get(NULL,
208                                         PACKAGE_LIB_DIR "/eina/modules/mp",
209                                         MODULE_ARCH);
210
211    path = eina_module_environment_path_get("HOME", "/.eina/mp/modules/mp");
212    _modules = eina_module_arch_list_get(_modules, path, MODULE_ARCH);
213    if (path)
214       free(path);
215
216    path = eina_module_environment_path_get("EINA_MODULES_MEMPOOL_DIR",
217                                            "/eina/modules/mp");
218    _modules = eina_module_arch_list_get(_modules, path, MODULE_ARCH);
219    if (path)
220       free(path);
221
222    path = eina_module_symbol_path_get((const void *)eina_init,
223                                       "/eina/modules/mp");
224    _modules = eina_module_arch_list_get(_modules, path, MODULE_ARCH);
225    if (path)
226       free(path);
227
228    if (!_modules)
229      {
230         ERR("no mempool modules able to be loaded.");
231         eina_hash_free(_backends);
232         goto mempool_init_error;
233      }
234
235    eina_module_list_load(_modules);
236
237    /* builtin backends */
238 #ifdef EINA_STATIC_BUILD_BUDDY
239    buddy_init();
240 #endif
241 #ifdef EINA_STATIC_BUILD_CHAINED_POOL
242    chained_init();
243 #endif
244 #ifdef EINA_STATIC_BUILD_EMEMOA_FIXED
245    ememoa_fixed_init();
246 #endif
247 #ifdef EINA_STATIC_BUILD_EMEMOA_UNKNOWN
248    ememoa_unknown_init();
249 #endif
250 #ifdef EINA_STATIC_BUILD_FIXED_BITMAP
251    fixed_bitmap_init();
252 #endif
253 #ifdef EINA_STATIC_BUILD_ONE_BIG
254    one_big_init();
255 #endif
256 #ifdef EINA_STATIC_BUILD_PASS_THROUGH
257    pass_through_init();
258 #endif
259
260    return EINA_TRUE;
261
262 mempool_init_error:
263    eina_log_domain_unregister(_eina_mempool_log_dom);
264    _eina_mempool_log_dom = -1;
265
266    return EINA_FALSE;
267 }
268
269 Eina_Bool
270 eina_mempool_shutdown(void)
271 {
272    /* builtin backends */
273 #ifdef EINA_STATIC_BUILD_BUDDY
274    buddy_shutdown();
275 #endif
276 #ifdef EINA_STATIC_BUILD_CHAINED_POOL
277    chained_shutdown();
278 #endif
279 #ifdef EINA_STATIC_BUILD_EMEMOA_FIXED
280    ememoa_fixed_shutdown();
281 #endif
282 #ifdef EINA_STATIC_BUILD_EMEMOA_UNKNOWN
283    ememoa_unknown_shutdown();
284 #endif
285 #ifdef EINA_STATIC_BUILD_FIXED_BITMAP
286    fixed_bitmap_shutdown();
287 #endif
288 #ifdef EINA_STATIC_BUILD_ONE_BIG
289    one_big_shutdown();
290 #endif
291 #ifdef EINA_STATIC_BUILD_PASS_THROUGH
292    pass_through_shutdown();
293 #endif
294    /* dynamic backends */
295    eina_module_list_free(_modules);
296    if (_modules)
297       eina_array_free(_modules);
298
299    if (_backends)
300       eina_hash_free(_backends);
301
302    eina_log_domain_unregister(_eina_mempool_log_dom);
303    _eina_mempool_log_dom = -1;
304
305    return EINA_TRUE;
306 }
307
308 /*============================================================================*
309 *                                   API                                      *
310 *============================================================================*/
311
312 EAPI Eina_Mempool *
313 eina_mempool_add(const char *name,
314                  const char *context,
315                  const char *options,
316                  ...)
317 {
318    Eina_Mempool *mp;
319    va_list args;
320
321    EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
322    DBG("name=%s, context=%s, options=%s",
323        name, context ? context : "", options ? options : "");
324
325    va_start(args, options);
326    mp = _new_va(name, context, options, args);
327    va_end(args);
328
329    DBG("name=%s, context=%s, options=%s, mp=%p",
330        name, context ? context : "", options ? options : "", mp);
331
332    return mp;
333 }
334
335 EAPI void eina_mempool_del(Eina_Mempool *mp)
336 {
337    EINA_SAFETY_ON_NULL_RETURN(mp);
338    EINA_SAFETY_ON_NULL_RETURN(mp->backend.shutdown);
339    DBG("mp=%p", mp);
340    mp->backend.shutdown(mp->backend_data);
341    free(mp->backend2);
342    free(mp);
343 }
344
345 EAPI void eina_mempool_repack(Eina_Mempool *mp, Eina_Mempool_Repack_Cb cb, void *data)
346 {
347    EINA_SAFETY_ON_NULL_RETURN(mp);
348    EINA_SAFETY_ON_NULL_RETURN(mp->backend2);
349    EINA_SAFETY_ON_NULL_RETURN(mp->backend2->repack);
350    DBG("mp=%p", mp);
351    mp->backend2->repack(mp->backend_data, cb, data);
352 }
353
354 EAPI void eina_mempool_gc(Eina_Mempool *mp)
355 {
356    EINA_SAFETY_ON_NULL_RETURN(mp);
357    EINA_SAFETY_ON_NULL_RETURN(mp->backend.garbage_collect);
358    DBG("mp=%p", mp);
359    mp->backend.garbage_collect(mp->backend_data);
360 }
361
362 EAPI void eina_mempool_statistics(Eina_Mempool *mp)
363 {
364    EINA_SAFETY_ON_NULL_RETURN(mp);
365    EINA_SAFETY_ON_NULL_RETURN(mp->backend.statistics);
366    DBG("mp=%p", mp);
367    mp->backend.statistics(mp->backend_data);
368 }
369
370 EAPI unsigned int
371 eina_mempool_alignof(unsigned int size)
372 {
373    int align;
374
375    if (size <= 2)
376       align = 2;
377    else if (size < 8)
378       align = 4;
379    else
380 #if __WORDSIZE == 32
381       align = 8;
382
383 #else
384    if (size < 16)
385       align = 8;
386    else
387       align = 16;
388 #endif
389
390    return ((size / align) + 1) * align;
391 }