diff --git a/src/lib/eina/eina_inline_mempool.x b/src/lib/eina/eina_inline_mempool.x index 0805c82f07..b0ab81587d 100644 --- a/src/lib/eina/eina_inline_mempool.x +++ b/src/lib/eina/eina_inline_mempool.x @@ -61,6 +61,11 @@ struct _Eina_Mempool_Backend * @use eina_mempool_iterator_new */ Eina_Iterator *(*iterator)(void *data); + /** Function to allocate memory near already allocated memory. + * @since 1.24 + * @use eina_mempool_malloc_near + */ + void *(*alloc_near)(void *data, void *after, void *before, unsigned int size); }; struct _Eina_Mempool_Backend_ABI1 @@ -80,6 +85,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); + void *(*alloc_near)(void *data, void *after, void *before, unsigned int size); }; struct _Eina_Mempool @@ -101,6 +107,14 @@ eina_mempool_malloc(Eina_Mempool *mp, unsigned int size) return mp->backend.alloc(mp->backend_data, size); } +static inline void * +eina_mempool_malloc_near(Eina_Mempool *mp, void *after, void *before, unsigned int size) +{ + if (mp->backend2 && mp->backend2->alloc_near && (!(after == NULL && before == NULL))) + return mp->backend2->alloc_near(mp->backend_data, after, before, size); + return mp->backend.alloc(mp->backend_data, size); +} + static inline void * eina_mempool_calloc(Eina_Mempool *mp, unsigned int size) { diff --git a/src/lib/eina/eina_mempool.c b/src/lib/eina/eina_mempool.c index 51a29906f2..93c32e9d7e 100644 --- a/src/lib/eina/eina_mempool.c +++ b/src/lib/eina/eina_mempool.c @@ -98,13 +98,14 @@ _new_va(const char *name, SBP(shutdown); #undef SBP - if (be->repack || be->from) + if (be->repack || be->from || be->iterator || be->alloc_near) { mp->backend2 = calloc(1, sizeof (Eina_Mempool_Backend_ABI2)); if (!mp->backend2) goto on_error; mp->backend2->repack = be->repack; mp->backend2->from = be->from; mp->backend2->iterator = be->iterator; + mp->backend2->alloc_near = be->alloc_near; } 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 d7759ce6c8..9b845c6565 100644 --- a/src/lib/eina/eina_mempool.h +++ b/src/lib/eina/eina_mempool.h @@ -124,6 +124,29 @@ static inline void *eina_mempool_realloc(Eina_Mempool *mp, void *element, unsign */ static inline void *eina_mempool_malloc(Eina_Mempool *mp, unsigned int size) EINA_MALLOC EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; +/** + * @brief Allocates memory in the given mempool using locality hint to improve future memory access use. + * + * @param[in] mp The mempool + * @param[in] after Hint to the nearest pointer after which to try find an empty spot. + * @param[in] before Hint to the nearest pointer before which to try find an empty spot. + * @param[in] size The size in bytes to allocate + * @return The newly allocated data that might be near @p after and @p before. + * + * This function is to be used to improve cache locality of structure that are likely to be used + * one after another. An example of this use would be Eina_List. + * + * @note This function allocates and returns @p size bytes using the mempool @p mp. + * If not used anymore, the data must be freed with eina_mempool_free(). + * @note @p after and @p before must be either @c NULL or allocated by the same mempool + * @p mp. They are hint and if no space near them is found, memory will be allocated + * without locality improvement. + * @warning No checks are done for @p mp. + * + * @see eina_mempool_free() + */ +static inline void *eina_mempool_malloc_near(Eina_Mempool *mp, void *after, void *before, unsigned int size) EINA_WARN_UNUSED_RESULT; + /** * @brief Allocates and zeros memory using the given mempool. * 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 f70339e080..1917e07921 100644 --- a/src/modules/eina/mp/chained_pool/eina_chained_mempool.c +++ b/src/modules/eina/mp/chained_pool/eina_chained_mempool.c @@ -726,7 +726,8 @@ static Eina_Mempool_Backend _eina_chained_mp_backend = { &eina_chained_mempool_shutdown, &eina_chained_mempool_repack, &eina_chained_mempool_from, - &eina_chained_mempool_iterator_new + &eina_chained_mempool_iterator_new, + NULL }; 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 b909dfbc51..50edfaab7b 100644 --- a/src/modules/eina/mp/one_big/eina_one_big.c +++ b/src/modules/eina/mp/one_big/eina_one_big.c @@ -452,7 +452,8 @@ static Eina_Mempool_Backend _eina_one_big_mp_backend = { &eina_one_big_shutdown, NULL, &eina_one_big_from, - &eina_one_big_iterator_new + &eina_one_big_iterator_new, + NULL }; 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 2d2bc3834a..652df39bf8 100644 --- a/src/modules/eina/mp/pass_through/eina_pass_through.c +++ b/src/modules/eina/mp/pass_through/eina_pass_through.c @@ -77,6 +77,7 @@ static Eina_Mempool_Backend _eina_pass_through_mp_backend = { &eina_pass_through_shutdown, NULL, &eina_pass_through_from, + NULL, NULL };