1 /* EINA - EFL data type library
2  * Copyright (C) 2008 Cedric Bail
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 #ifndef EINA_INLINE_MEMPOOL_X_
20 #define EINA_INLINE_MEMPOOL_X_
21 
22 #include <string.h>
23 
24 /* Memory Pool */
25 typedef struct _Eina_Mempool_Backend_ABI1 Eina_Mempool_Backend_ABI1;
26 typedef struct _Eina_Mempool_Backend_ABI2 Eina_Mempool_Backend_ABI2;
27 
28 struct _Eina_Mempool_Backend
29 {
30    /** Name of the mempool backend */
31    const char *name;
32    /** Function to initialize the backend. */
33    void *(*init)(const char *context, const char *options, va_list args);
34    /** Function to free memory back to the mempool. */
35    void (*free)(void *data, void *element);
36    /** Function to allocate memory from the mempool. */
37    void *(*alloc)(void *data, unsigned int size);
38    /** Function to change the size of a block of memory that is currently
39     * allocated. */
40    void *(*realloc)(void *data, void *element, unsigned int size);
41    /** Function to trigger a garbage collection; can be NULL if the feature
42     * isn't available in the backend. */
43    void (*garbage_collect)(void *data);
44    /** Report statistics on the content of the mempool; can be NULL if the
45     * feature isn't available in the backend. */
46    void (*statistics)(void *data);
47    /** Function to destroy the backend, freeing memory back to the operating
48     * system. */
49    void (*shutdown)(void *data);
50    /** Function to optimize the placement of objects in the mempool (it's
51     * different from garbage_collect); can be NULL if the feature isn't
52     * available in the backend.
53     * @see Eina_Mempool_Repack_Cb */
54    void (*repack)(void *data, Eina_Mempool_Repack_Cb cb, void *cb_data);
55    /** Function to check is a valid element from a mempool.
56     * @see eina_mempool_from
57     */
58    Eina_Bool (*from)(void *data, void *element);
59    /** Function to get an Eina_Iterator that will walk every allocated element
60     * in the pool.
61     * @see eina_mempool_iterator_new
62     */
63    Eina_Iterator *(*iterator)(void *data);
64    /** Function to allocate memory near already allocated memory.
65     * @since 1.24
66     * @see eina_mempool_malloc_near
67     */
68    void *(*alloc_near)(void *data, void *after, void *before, unsigned int size);
69 };
70 
71 struct _Eina_Mempool_Backend_ABI1
72 {
73    const char *name;
74    void *(*init)(const char *context, const char *options, va_list args);
75    void (*free)(void *data, void *element);
76    void *(*alloc)(void *data, unsigned int size);
77    void *(*realloc)(void *data, void *element, unsigned int size);
78    void (*garbage_collect)(void *data);
79    void (*statistics)(void *data);
80    void (*shutdown)(void *data);
81 };
82 
83 struct _Eina_Mempool_Backend_ABI2
84 {
85    void (*repack)(void *data, Eina_Mempool_Repack_Cb cb, void *cb_data);
86    Eina_Bool (*from)(void *data, void *element);
87    Eina_Iterator *(*iterator)(void *data);
88    void *(*alloc_near)(void *data, void *after, void *before, unsigned int size);
89 };
90 
91 struct _Eina_Mempool
92 {
93    Eina_Mempool_Backend_ABI1 backend;
94    void *backend_data;
95    Eina_Mempool_Backend_ABI2 *backend2;
96 };
97 
98 static inline void *
eina_mempool_realloc(Eina_Mempool * mp,void * element,unsigned int size)99 eina_mempool_realloc(Eina_Mempool *mp, void *element, unsigned int size)
100 {
101    return mp->backend.realloc(mp->backend_data, element, size);
102 }
103 
104 static inline void *
eina_mempool_malloc(Eina_Mempool * mp,unsigned int size)105 eina_mempool_malloc(Eina_Mempool *mp, unsigned int size)
106 {
107    return mp->backend.alloc(mp->backend_data, size);
108 }
109 
110 static inline void *
eina_mempool_malloc_near(Eina_Mempool * mp,void * after,void * before,unsigned int size)111 eina_mempool_malloc_near(Eina_Mempool *mp, void *after, void *before, unsigned int size)
112 {
113    if (mp->backend2 && mp->backend2->alloc_near && (!(after == NULL && before == NULL)))
114      return mp->backend2->alloc_near(mp->backend_data, after, before, size);
115    return mp->backend.alloc(mp->backend_data, size);
116 }
117 
118 static inline void *
eina_mempool_calloc(Eina_Mempool * mp,unsigned int size)119 eina_mempool_calloc(Eina_Mempool *mp, unsigned int size)
120 {
121    void *r = mp->backend.alloc(mp->backend_data, size);
122    if (r) memset(r, 0, size);
123    return r;
124 }
125 
126 static inline void
eina_mempool_free(Eina_Mempool * mp,void * element)127 eina_mempool_free(Eina_Mempool *mp, void *element)
128 {
129    if (element) mp->backend.free(mp->backend_data, element);
130 }
131 
132 static inline Eina_Bool
eina_mempool_from(Eina_Mempool * mp,void * element)133 eina_mempool_from(Eina_Mempool *mp, void *element)
134 {
135    if (!element) return EINA_FALSE;
136    return mp->backend2->from(mp->backend_data, element);
137 }
138 
139 static inline Eina_Iterator *
eina_mempool_iterator_new(Eina_Mempool * mp)140 eina_mempool_iterator_new(Eina_Mempool *mp)
141 {
142    if (!mp->backend2->iterator) return NULL;
143    return mp->backend2->iterator(mp->backend_data);
144 }
145 
146 static inline unsigned int
eina_mempool_alignof(unsigned int size)147 eina_mempool_alignof(unsigned int size)
148 {
149    unsigned int align;
150 
151 #if __WORDSIZE == 32
152    if (size >= 8)
153      {
154         align = 8;
155 calc:
156         return ((size / align) + (size % align ? 1 : 0)) * align;
157      }
158 #else // __WORDSIZE == 64
159    if (size >= 16)
160      {
161         align = 16;
162 calc:
163         return ((size / align) + (size % align ? 1 : 0)) * align;
164      }
165    else if (size >= 8)
166      {
167         align = 8;
168         goto calc;
169      }
170 #endif
171    else if (size >= 4)
172      {
173         align = 4;
174         goto calc;
175      }
176    align = 2;
177    goto calc;
178 }
179 
180 #endif
181