summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/eina/eina_inline_mempool.x13
-rw-r--r--src/lib/eina/eina_mempool.c1
-rw-r--r--src/lib/eina/eina_mempool.h11
-rw-r--r--src/modules/eina/mp/chained_pool/eina_chained_mempool.c94
-rw-r--r--src/modules/eina/mp/one_big/eina_one_big.c82
-rw-r--r--src/modules/eina/mp/pass_through/eina_pass_through.c3
-rw-r--r--src/tests/eina/eina_test_mempool.c18
7 files changed, 209 insertions, 13 deletions
diff --git a/src/lib/eina/eina_inline_mempool.x b/src/lib/eina/eina_inline_mempool.x
index d30364f097..0805c82f07 100644
--- a/src/lib/eina/eina_inline_mempool.x
+++ b/src/lib/eina/eina_inline_mempool.x
@@ -56,6 +56,11 @@ struct _Eina_Mempool_Backend
* @see eina_mempool_from
*/
Eina_Bool (*from)(void *data, void *element);
+ /** Function to get an Eina_Iterator that will walk every allocated element
+ * in the pool.
+ * @use eina_mempool_iterator_new
+ */
+ Eina_Iterator *(*iterator)(void *data);
};
struct _Eina_Mempool_Backend_ABI1
@@ -74,6 +79,7 @@ struct _Eina_Mempool_Backend_ABI2
{
void (*repack)(void *data, Eina_Mempool_Repack_Cb cb, void *cb_data);
Eina_Bool (*from)(void *data, void *element);
+ Eina_Iterator *(*iterator)(void *data);
};
struct _Eina_Mempool
@@ -116,6 +122,13 @@ eina_mempool_from(Eina_Mempool *mp, void *element)
return mp->backend2->from(mp->backend_data, element);
}
+static inline Eina_Iterator *
+eina_mempool_iterator_new(Eina_Mempool *mp)
+{
+ if (!mp->backend2->iterator) return NULL;
+ return mp->backend2->iterator(mp->backend_data);
+}
+
static inline unsigned int
eina_mempool_alignof(unsigned int size)
{
diff --git a/src/lib/eina/eina_mempool.c b/src/lib/eina/eina_mempool.c
index 56144a0f1c..51a29906f2 100644
--- a/src/lib/eina/eina_mempool.c
+++ b/src/lib/eina/eina_mempool.c
@@ -104,6 +104,7 @@ _new_va(const char *name,
if (!mp->backend2) goto on_error;
mp->backend2->repack = be->repack;
mp->backend2->from = be->from;
+ mp->backend2->iterator = be->iterator;
}
mp->backend_data = mp->backend.init(context, options, args);
diff --git a/src/lib/eina/eina_mempool.h b/src/lib/eina/eina_mempool.h
index 606ecbaef9..d7759ce6c8 100644
--- a/src/lib/eina/eina_mempool.h
+++ b/src/lib/eina/eina_mempool.h
@@ -198,6 +198,17 @@ static inline Eina_Bool eina_mempool_from(Eina_Mempool *mp, void *element);
EAPI void eina_mempool_statistics(Eina_Mempool *mp) EINA_ARG_NONNULL(1);
/**
+ * @brief Provide an iterator to walk all allocated elements from a specified mempool.
+ *
+ * @param[in] mp The mempool
+ * @return @c NULL if it is not possible to iterate over the mempool, a valid iterator otherwise.
+ *
+ * @note This call is expected to be slow and should not be used in any performance critical area.
+ * @since 1.23
+ */
+static inline Eina_Iterator *eina_mempool_iterator_new(Eina_Mempool *mp);
+
+/**
* @brief Registers the given memory pool backend.
*
* @param[in] be The backend
diff --git a/src/modules/eina/mp/chained_pool/eina_chained_mempool.c b/src/modules/eina/mp/chained_pool/eina_chained_mempool.c
index d44f0bf6cb..6d4facf74d 100644
--- a/src/modules/eina/mp/chained_pool/eina_chained_mempool.c
+++ b/src/modules/eina/mp/chained_pool/eina_chained_mempool.c
@@ -79,7 +79,7 @@ struct _Chained_Pool
EINA_INLIST;
EINA_RBTREE;
Eina_Trash *base;
- int usage;
+ unsigned int usage;
unsigned char *last;
unsigned char *limit;
@@ -91,11 +91,11 @@ struct _Chained_Mempool
Eina_Inlist *first;
Eina_Rbtree *root;
const char *name;
- int item_alloc;
- int pool_size;
- int alloc_size;
- int group_size;
- int usage;
+ unsigned int item_alloc;
+ unsigned int pool_size;
+ unsigned int alloc_size;
+ unsigned int group_size;
+ unsigned int usage;
Chained_Pool* first_fill; //All allocation will happen in this chain,unless it is filled
#ifdef EINA_DEBUG_MALLOC
int minimal_size;
@@ -453,6 +453,85 @@ eina_chained_mempool_from(void *data, void *ptr)
return ret;
}
+typedef struct _Eina_Iterator_Chained_Mempool Eina_Iterator_Chained_Mempool;
+struct _Eina_Iterator_Chained_Mempool
+{
+ Eina_Iterator iterator;
+
+ Eina_Iterator *walker;
+ Chained_Pool *current;
+ Chained_Mempool *pool;
+
+ unsigned int offset;
+};
+
+static Eina_Bool
+eina_mempool_iterator_next(Eina_Iterator_Chained_Mempool *it, void **data)
+{
+ if (!it->current)
+ {
+ if (!eina_iterator_next(it->walker, (void**) &it->current))
+ return EINA_FALSE;
+ if (!it->current) return EINA_FALSE;
+ }
+
+ retry:
+ if (it->offset < it->pool->group_size)
+ {
+ unsigned char *ptr = (unsigned char *) (it->current + 1);
+
+ ptr += it->offset;
+ it->offset += it->pool->item_alloc;
+
+ if (!eina_chained_mempool_from(it->pool, ptr)) goto retry;
+
+ if (data) *data = (void *) ptr;
+ return EINA_TRUE;
+ }
+
+ if (!eina_iterator_next(it->walker, (void**) &it->current))
+ return EINA_FALSE;
+
+ it->offset = 0;
+ goto retry;
+}
+
+static Chained_Mempool *
+eina_mempool_iterator_get_container(Eina_Iterator_Chained_Mempool *it)
+{
+ return it->pool;
+}
+
+static void
+eina_mempool_iterator_free(Eina_Iterator_Chained_Mempool *it)
+{
+ eina_iterator_free(it->walker);
+ free(it);
+}
+
+static Eina_Iterator *
+eina_chained_mempool_iterator_new(void *data)
+{
+ Eina_Iterator_Chained_Mempool *it;
+ Chained_Mempool *pool = data;
+
+ it = calloc(1, sizeof (Eina_Iterator_Chained_Mempool));
+ if (!it) return NULL;
+
+ it->walker = eina_inlist_iterator_new(pool->first);
+ it->pool = pool;
+
+ it->iterator.version = EINA_ITERATOR_VERSION;
+ it->iterator.next = FUNC_ITERATOR_NEXT(eina_mempool_iterator_next);
+ it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
+ eina_mempool_iterator_get_container);
+ it->iterator.free = FUNC_ITERATOR_FREE(eina_mempool_iterator_free);
+
+ EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
+
+ return &it->iterator;
+}
+
static void
eina_chained_mempool_repack(void *data,
Eina_Mempool_Repack_Cb cb,
@@ -645,7 +724,8 @@ static Eina_Mempool_Backend _eina_chained_mp_backend = {
NULL,
&eina_chained_mempool_shutdown,
&eina_chained_mempool_repack,
- &eina_chained_mempool_from
+ &eina_chained_mempool_from,
+ &eina_chained_mempool_iterator_new
};
Eina_Bool chained_init(void)
diff --git a/src/modules/eina/mp/one_big/eina_one_big.c b/src/modules/eina/mp/one_big/eina_one_big.c
index 39fd511cf1..b909dfbc51 100644
--- a/src/modules/eina/mp/one_big/eina_one_big.c
+++ b/src/modules/eina/mp/one_big/eina_one_big.c
@@ -63,14 +63,14 @@ struct _One_Big
{
const char *name;
- int item_size;
+ unsigned int item_size;
int offset_to_item_inlist;
int usage;
int over;
- int served;
- int max;
+ unsigned int served;
+ unsigned int max;
unsigned char *base;
Eina_Trash *empty;
@@ -263,6 +263,79 @@ eina_one_big_from(void *data, void *ptr)
return r;
}
+typedef struct _Eina_Iterator_One_Big_Mempool Eina_Iterator_One_Big_Mempool;
+struct _Eina_Iterator_One_Big_Mempool
+{
+ Eina_Iterator iterator;
+
+ Eina_Iterator *walker;
+ One_Big *pool;
+
+ unsigned int offset;
+};
+
+static Eina_Bool
+eina_mempool_iterator_next(Eina_Iterator_One_Big_Mempool *it, void **data)
+{
+ Eina_Inlist *il = NULL;
+
+ retry:
+ if (it->offset < (it->pool->max * it->pool->item_size))
+ {
+ unsigned char *ptr = (unsigned char *) (it->pool->base);
+
+ ptr += it->offset;
+ it->offset += it->pool->item_size;
+
+ if (!eina_one_big_from(it->pool, ptr)) goto retry;
+
+ if (data) *data = (void *) ptr;
+ return EINA_TRUE;
+ }
+
+ if (!eina_iterator_next(it->walker, (void **) &il))
+ return EINA_FALSE;
+
+ if (data) *data = OVER_MEM_FROM_LIST(it->pool, il);
+ return EINA_TRUE;
+}
+
+static One_Big *
+eina_mempool_iterator_get_container(Eina_Iterator_One_Big_Mempool *it)
+{
+ return it->pool;
+}
+
+static void
+eina_mempool_iterator_free(Eina_Iterator_One_Big_Mempool *it)
+{
+ eina_iterator_free(it->walker);
+ free(it);
+}
+
+static Eina_Iterator *
+eina_one_big_iterator_new(void *data)
+{
+ Eina_Iterator_One_Big_Mempool *it;
+ One_Big *pool = data;
+
+ it = calloc(1, sizeof (Eina_Iterator_One_Big_Mempool));
+ if (!it) return NULL;
+
+ it->walker = eina_inlist_iterator_new(pool->over_list);
+ it->pool = pool;
+
+ it->iterator.version = EINA_ITERATOR_VERSION;
+ it->iterator.next = FUNC_ITERATOR_NEXT(eina_mempool_iterator_next);
+ it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
+ eina_mempool_iterator_get_container);
+ it->iterator.free = FUNC_ITERATOR_FREE(eina_mempool_iterator_free);
+
+ EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
+
+ return &it->iterator;
+}
+
static void *
eina_one_big_realloc(EINA_UNUSED void *data,
EINA_UNUSED void *element,
@@ -378,7 +451,8 @@ static Eina_Mempool_Backend _eina_one_big_mp_backend = {
NULL,
&eina_one_big_shutdown,
NULL,
- &eina_one_big_from
+ &eina_one_big_from,
+ &eina_one_big_iterator_new
};
Eina_Bool one_big_init(void)
diff --git a/src/modules/eina/mp/pass_through/eina_pass_through.c b/src/modules/eina/mp/pass_through/eina_pass_through.c
index 0e546f7987..2d2bc3834a 100644
--- a/src/modules/eina/mp/pass_through/eina_pass_through.c
+++ b/src/modules/eina/mp/pass_through/eina_pass_through.c
@@ -76,7 +76,8 @@ static Eina_Mempool_Backend _eina_pass_through_mp_backend = {
NULL,
&eina_pass_through_shutdown,
NULL,
- &eina_pass_through_from
+ &eina_pass_through_from,
+ NULL
};
Eina_Bool pass_through_init(void)
diff --git a/src/tests/eina/eina_test_mempool.c b/src/tests/eina/eina_test_mempool.c
index 78656cea53..c36bab1717 100644
--- a/src/tests/eina/eina_test_mempool.c
+++ b/src/tests/eina/eina_test_mempool.c
@@ -28,10 +28,12 @@ static void
_eina_mempool_test(Eina_Mempool *mp,
Eina_Bool with_realloc, Eina_Bool with_gc, Eina_Bool accurate_from)
{
+ Eina_Iterator *it;
int *tbl[512];
+ int *ptr;
int i;
- fail_if(!mp);
+ fail_if(!mp);
for (i = 0; i < 512; ++i)
{
@@ -52,6 +54,20 @@ _eina_mempool_test(Eina_Mempool *mp,
fail_if(eina_mempool_from(mp, tbl[i]) != EINA_FALSE);
}
+ it = eina_mempool_iterator_new(mp);
+ EINA_ITERATOR_FOREACH(it, ptr)
+ {
+ ck_assert_int_gt(*ptr, 255);
+ *ptr = 0;
+ }
+ eina_iterator_free(it);
+
+ if (it) // Only check if the mempool support iterator
+ {
+ for (; i < 512; ++i)
+ ck_assert_int_eq(*tbl[i], 0);
+ }
+
if (with_realloc)
fail_if(eina_mempool_realloc(mp, tbl[500], 25) == NULL);
else