forked from enlightenment/efl
eina: add eina_mempool_iterator_new to slowly iterate every allocated pointer in a mempool.
Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Differential Revision: https://phab.enlightenment.org/D9941
This commit is contained in:
parent
bf12fe241e
commit
9382bfc0bc
|
@ -56,6 +56,11 @@ struct _Eina_Mempool_Backend
|
||||||
* @see eina_mempool_from
|
* @see eina_mempool_from
|
||||||
*/
|
*/
|
||||||
Eina_Bool (*from)(void *data, void *element);
|
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
|
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);
|
void (*repack)(void *data, Eina_Mempool_Repack_Cb cb, void *cb_data);
|
||||||
Eina_Bool (*from)(void *data, void *element);
|
Eina_Bool (*from)(void *data, void *element);
|
||||||
|
Eina_Iterator *(*iterator)(void *data);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Eina_Mempool
|
struct _Eina_Mempool
|
||||||
|
@ -116,6 +122,13 @@ eina_mempool_from(Eina_Mempool *mp, void *element)
|
||||||
return mp->backend2->from(mp->backend_data, 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
|
static inline unsigned int
|
||||||
eina_mempool_alignof(unsigned int size)
|
eina_mempool_alignof(unsigned int size)
|
||||||
{
|
{
|
||||||
|
|
|
@ -104,6 +104,7 @@ _new_va(const char *name,
|
||||||
if (!mp->backend2) goto on_error;
|
if (!mp->backend2) goto on_error;
|
||||||
mp->backend2->repack = be->repack;
|
mp->backend2->repack = be->repack;
|
||||||
mp->backend2->from = be->from;
|
mp->backend2->from = be->from;
|
||||||
|
mp->backend2->iterator = be->iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp->backend_data = mp->backend.init(context, options, args);
|
mp->backend_data = mp->backend.init(context, options, args);
|
||||||
|
|
|
@ -197,6 +197,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);
|
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.
|
* @brief Registers the given memory pool backend.
|
||||||
*
|
*
|
||||||
|
|
|
@ -79,7 +79,7 @@ struct _Chained_Pool
|
||||||
EINA_INLIST;
|
EINA_INLIST;
|
||||||
EINA_RBTREE;
|
EINA_RBTREE;
|
||||||
Eina_Trash *base;
|
Eina_Trash *base;
|
||||||
int usage;
|
unsigned int usage;
|
||||||
|
|
||||||
unsigned char *last;
|
unsigned char *last;
|
||||||
unsigned char *limit;
|
unsigned char *limit;
|
||||||
|
@ -91,11 +91,11 @@ struct _Chained_Mempool
|
||||||
Eina_Inlist *first;
|
Eina_Inlist *first;
|
||||||
Eina_Rbtree *root;
|
Eina_Rbtree *root;
|
||||||
const char *name;
|
const char *name;
|
||||||
int item_alloc;
|
unsigned int item_alloc;
|
||||||
int pool_size;
|
unsigned int pool_size;
|
||||||
int alloc_size;
|
unsigned int alloc_size;
|
||||||
int group_size;
|
unsigned int group_size;
|
||||||
int usage;
|
unsigned int usage;
|
||||||
Chained_Pool* first_fill; //All allocation will happen in this chain,unless it is filled
|
Chained_Pool* first_fill; //All allocation will happen in this chain,unless it is filled
|
||||||
#ifdef EINA_DEBUG_MALLOC
|
#ifdef EINA_DEBUG_MALLOC
|
||||||
int minimal_size;
|
int minimal_size;
|
||||||
|
@ -453,6 +453,85 @@ eina_chained_mempool_from(void *data, void *ptr)
|
||||||
return ret;
|
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
|
static void
|
||||||
eina_chained_mempool_repack(void *data,
|
eina_chained_mempool_repack(void *data,
|
||||||
Eina_Mempool_Repack_Cb cb,
|
Eina_Mempool_Repack_Cb cb,
|
||||||
|
@ -645,7 +724,8 @@ static Eina_Mempool_Backend _eina_chained_mp_backend = {
|
||||||
NULL,
|
NULL,
|
||||||
&eina_chained_mempool_shutdown,
|
&eina_chained_mempool_shutdown,
|
||||||
&eina_chained_mempool_repack,
|
&eina_chained_mempool_repack,
|
||||||
&eina_chained_mempool_from
|
&eina_chained_mempool_from,
|
||||||
|
&eina_chained_mempool_iterator_new
|
||||||
};
|
};
|
||||||
|
|
||||||
Eina_Bool chained_init(void)
|
Eina_Bool chained_init(void)
|
||||||
|
|
|
@ -63,14 +63,14 @@ struct _One_Big
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
int item_size;
|
unsigned int item_size;
|
||||||
int offset_to_item_inlist;
|
int offset_to_item_inlist;
|
||||||
|
|
||||||
int usage;
|
int usage;
|
||||||
int over;
|
int over;
|
||||||
|
|
||||||
int served;
|
unsigned int served;
|
||||||
int max;
|
unsigned int max;
|
||||||
unsigned char *base;
|
unsigned char *base;
|
||||||
|
|
||||||
Eina_Trash *empty;
|
Eina_Trash *empty;
|
||||||
|
@ -263,6 +263,79 @@ eina_one_big_from(void *data, void *ptr)
|
||||||
return r;
|
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 *
|
static void *
|
||||||
eina_one_big_realloc(EINA_UNUSED void *data,
|
eina_one_big_realloc(EINA_UNUSED void *data,
|
||||||
EINA_UNUSED void *element,
|
EINA_UNUSED void *element,
|
||||||
|
@ -378,7 +451,8 @@ static Eina_Mempool_Backend _eina_one_big_mp_backend = {
|
||||||
NULL,
|
NULL,
|
||||||
&eina_one_big_shutdown,
|
&eina_one_big_shutdown,
|
||||||
NULL,
|
NULL,
|
||||||
&eina_one_big_from
|
&eina_one_big_from,
|
||||||
|
&eina_one_big_iterator_new
|
||||||
};
|
};
|
||||||
|
|
||||||
Eina_Bool one_big_init(void)
|
Eina_Bool one_big_init(void)
|
||||||
|
|
|
@ -76,7 +76,8 @@ static Eina_Mempool_Backend _eina_pass_through_mp_backend = {
|
||||||
NULL,
|
NULL,
|
||||||
&eina_pass_through_shutdown,
|
&eina_pass_through_shutdown,
|
||||||
NULL,
|
NULL,
|
||||||
&eina_pass_through_from
|
&eina_pass_through_from,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
Eina_Bool pass_through_init(void)
|
Eina_Bool pass_through_init(void)
|
||||||
|
|
|
@ -28,7 +28,9 @@ static void
|
||||||
_eina_mempool_test(Eina_Mempool *mp,
|
_eina_mempool_test(Eina_Mempool *mp,
|
||||||
Eina_Bool with_realloc, Eina_Bool with_gc, Eina_Bool accurate_from)
|
Eina_Bool with_realloc, Eina_Bool with_gc, Eina_Bool accurate_from)
|
||||||
{
|
{
|
||||||
|
Eina_Iterator *it;
|
||||||
int *tbl[512];
|
int *tbl[512];
|
||||||
|
int *ptr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fail_if(!mp);
|
fail_if(!mp);
|
||||||
|
@ -52,6 +54,20 @@ _eina_mempool_test(Eina_Mempool *mp,
|
||||||
fail_if(eina_mempool_from(mp, tbl[i]) != EINA_FALSE);
|
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)
|
if (with_realloc)
|
||||||
fail_if(eina_mempool_realloc(mp, tbl[500], 25) == NULL);
|
fail_if(eina_mempool_realloc(mp, tbl[500], 25) == NULL);
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue