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
|
||||
*/
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue