diff --git a/legacy/eina/src/include/Eina.h b/legacy/eina/src/include/Eina.h index 96ac93dff4..997e0d476e 100644 --- a/legacy/eina/src/include/Eina.h +++ b/legacy/eina/src/include/Eina.h @@ -36,6 +36,7 @@ *
  • @ref eina_hash_subsubsec *
  • @ref eina_inlist_subsubsec *
  • @ref eina_rbtree_subsubsec + *
  • @ref eina_trash_subsubsec *
  • @ref eina_list_subsubsec * *
  • @ref eina_stringshare_subsec @@ -92,6 +93,10 @@ * * @subsubsection eina_rbtree_subsubsec Inlined Red Black Tree * + * @subsubsection eina_trash_subsubsec Trash + * + * @subsubsection eina_trash_subsubsec Trash + * * @subsubsection eina_list_subsubsec List * * @subsection eina_stringshare_subsec Shared String @@ -145,6 +150,7 @@ extern "C" { #include "eina_file.h" #include "eina_list.h" #include "eina_hash.h" +#include "eina_trash.h" #include "eina_lalloc.h" #include "eina_module.h" #include "eina_mempool.h" diff --git a/legacy/eina/src/include/Makefile.am b/legacy/eina/src/include/Makefile.am index 64b5782c9d..c02a04d565 100644 --- a/legacy/eina/src/include/Makefile.am +++ b/legacy/eina/src/include/Makefile.am @@ -28,6 +28,8 @@ eina_benchmark.h \ eina_inline_rbtree.x \ eina_inline_mempool.x \ eina_inline_rectangle.x \ +eina_inline_trash.x \ +eina_trash.h \ eina_iterator.h \ eina_main.h \ eina_cpu.h \ diff --git a/legacy/eina/src/include/eina_inline_trash.x b/legacy/eina/src/include/eina_inline_trash.x new file mode 100644 index 0000000000..37a703045a --- /dev/null +++ b/legacy/eina/src/include/eina_inline_trash.x @@ -0,0 +1,90 @@ +/* EINA - EFL data type library + * Copyright (C) 2008 Cedric Bail + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifndef EINA_INLINE_TRASH_X__ +#define EINA_INLINE_TRASH_X__ + +/** + * @brief Initialize a trash before using it. + * + * @param trash The trash. + * + * This function just set to zero the trash to correctly + * initialize it. + * + * @note You can just set *trash to NULL and you will have + * the same result. + */ +static inline void +eina_trash_init(Eina_Trash **trash) +{ + *trash = NULL; +} + +/** + * @brief Push an unused pointer in the trash instead of freeing it. + * + * @param trash A pointer to an Eina_Trash. + * @param data An unused pointer big enougth to put a (void*). + * + * Instead of freeing a pointer and put pressure on malloc/free + * you can push it in a trash for a later use. This function just + * provide a fast way to push a now unused pointer into a trash. + * + * @note Do never use the pointer after insertion or bad things will + * happens. + * + * @note This trash will not resize, nor do anything with the size of + * the region pointed by @p data, so it's your duty to manage the size. + */ +static inline void +eina_trash_push(Eina_Trash **trash, void *data) +{ + Eina_Trash *tmp; + + tmp = data; + tmp->next = *trash; + *trash = tmp; +} + +/** + * @brief Pop an available pointer from the trash if possible. + * + * @param trash A pointer to an Eina_Trash. + * + * Instead of calling malloc, and putting pressure on malloc/free + * you can recycle the content of the trash, if it's not empty. + * + * @note This trash will not resize, nor do anything with the size of + * the region pointed by pointer inside the trash, so it's your duty + * to manage the size of the returned pointer. + */ +static inline void* +eina_trash_pop(Eina_Trash **trash) +{ + void *tmp; + + tmp = *trash; + + if (*trash != NULL) + *trash = (*trash)->next; + + return tmp; +} + +#endif diff --git a/legacy/eina/src/include/eina_trash.h b/legacy/eina/src/include/eina_trash.h new file mode 100644 index 0000000000..358fb62f02 --- /dev/null +++ b/legacy/eina/src/include/eina_trash.h @@ -0,0 +1,100 @@ +/* EINA - EFL data type library + * Copyright (C) 2002-2008 Carsten Haitzler, Vincent Torri, Jorge Luis Zapata Muga + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifndef EINA_TRASH_H__ +#define EINA_TRASH_H__ + +/** + * @addtogroup Eina_Data_Types_Group Data Types + * + * @{ + */ + +/** + * @addtogroup Eina_Containers_Group Containers + * + * @{ + */ + +/** + * @defgroup Eina_Trash_Group Trash + * + * @{ + */ + +/** + * @typedef Eina_Trash + * Type for a generic container of unused allocated pointer. + */ +typedef struct _Eina_Trash Eina_Trash; + +/** + * @struct _Eina_Trash + * Type for a generic container of unused allocated pointer. + */ +struct _Eina_Trash +{ + Eina_Trash *next; +}; + +static inline void eina_trash_init(Eina_Trash **trash) EINA_ARG_NONNULL(1); +static inline void eina_trash_push(Eina_Trash **trash, void *data) EINA_ARG_NONNULL(1); +static inline void *eina_trash_pop(Eina_Trash **trash) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; + +/** + * @def EINA_TRASH_FOREACH + * @brief Macro to remove all pointer from the trash. + * + * @param trash The trash to clean. + * @param data The pointer extracted from the trash. + * + * This macro allow the cleaning of @p trash in an easy way. It will + * remove all pointers from @p trash until it's empty. + * + * This macro can be used for freeing the data in the trash, like in + * the following example: + * + * @code + * Eina_Trash *trash = NULL; + * char *data; + * + * // trash is filled with pointer to some duped strings. + * + * EINA_TRASH_CLEAN(&trash, data) + * free(data); + * @endcode + * + * @note this macro is usefull when you implement some memory pool. + */ +#define EINA_TRASH_CLEAN(trash, data) while ((data = eina_trash_pop(trash)) + +#include "eina_inline_trash.x" + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* EINA_TRASH_H_ */ diff --git a/legacy/eina/src/modules/mp/chained_pool/eina_chained_mempool.c b/legacy/eina/src/modules/mp/chained_pool/eina_chained_mempool.c index 4c2c8af3e4..7d82195d5f 100644 --- a/legacy/eina/src/modules/mp/chained_pool/eina_chained_mempool.c +++ b/legacy/eina/src/modules/mp/chained_pool/eina_chained_mempool.c @@ -34,6 +34,7 @@ #include "eina_error.h" #include "eina_module.h" #include "eina_mempool.h" +#include "eina_trash.h" #include "eina_private.h" @@ -54,7 +55,7 @@ typedef struct _Chained_Pool Chained_Pool; struct _Chained_Pool { EINA_INLIST; - void *base; + Eina_Trash *base; int usage; }; @@ -62,20 +63,16 @@ static inline Chained_Pool * _eina_chained_mp_pool_new(Chained_Mempool *pool) { Chained_Pool *p; - void **ptr; + unsigned char *ptr; int item_alloc, i; item_alloc = ((pool->item_size + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *); p = malloc(sizeof(Chained_Pool) + (pool->pool_size * item_alloc)); - ptr = (void **)(((unsigned char *)p) + sizeof(Chained_Pool)); + ptr = (unsigned char *) (p + 1); p->usage = 0; - p->base = ptr; - for (i = 0; i < pool->pool_size - 1; i++) - { - *ptr = (void **)(((unsigned char *)ptr) + item_alloc); - ptr = *ptr; - } - *ptr = NULL; + p->base = NULL; + for (i = 0; i < pool->pool_size; ++i, ptr += item_alloc) + eina_trash_push(&p->base, ptr); return p; } @@ -120,10 +117,8 @@ eina_chained_mempool_malloc(void *data, __UNUSED__ unsigned int size) } pool->first = eina_inlist_prepend(pool->first, EINA_INLIST_GET(p)); } - // this points to the next free block - so take it - mem = p->base; - // base now points to the next free block - p->base = *((void **)mem); + // Request a free pointer + mem = eina_trash_pop(&p->base); // move to end - it just filled up if (!p->base) { @@ -162,9 +157,8 @@ eina_chained_mempool_free(void *data, void *ptr) if ((ptr >= pmem) && ((unsigned char *)ptr < (((unsigned char *)pmem) + psize))) { // freed node points to prev free node - *((void **)ptr) = p->base; + eina_trash_push(&p->base, ptr); // next free node is now the one we freed - p->base = ptr; p->usage--; pool->usage--; if (p->usage == 0)