eina_value: use mempool.

thanks to discomfitor about the tip.



SVN revision: 67151
This commit is contained in:
Gustavo Sverzut Barbieri 2012-01-12 18:50:43 +00:00
parent 90e2259b6f
commit 9d424b133b
3 changed files with 202 additions and 18 deletions

View File

@ -92,6 +92,19 @@ eina_value_memory_get(const Eina_Value *value)
return value->value.ptr;
}
/**
* @brief Allocate memory for internal value types.
* @since 1.2
* @private
*/
EAPI void *eina_value_inner_alloc(size_t size);
/**
* @brief Releases memory for internal value types.
* @since 1.2
* @private
*/
EAPI void eina_value_inner_free(size_t size, void *mem);
static inline Eina_Bool
eina_value_setup(Eina_Value *value, const Eina_Value_Type *type)
{
@ -102,17 +115,15 @@ eina_value_setup(Eina_Value *value, const Eina_Value_Type *type)
value->type = type;
if (type->value_size <= 8)
{
mem = &value->value;
memset(mem, 0, type->value_size);
}
if (type->value_size <= 8) mem = &value->value;
else
{
mem = value->value.ptr = calloc(1, type->value_size);
mem = value->value.ptr = eina_value_inner_alloc(type->value_size);
EINA_SAFETY_ON_NULL_RETURN_VAL(mem, EINA_FALSE);
}
memset(mem, 0, type->value_size);
if (EINA_VALUE_TYPE_DEFAULT(type))
{
eina_error_set(0);
@ -144,13 +155,15 @@ eina_value_flush(Eina_Value *value)
{
if (value->value.ptr) free(value->value.ptr);
}
else if (type->value_size > 8) free(mem);
else if (type->value_size > 8)
eina_value_inner_free(type->value_size, mem);
eina_error_set(0);
return;
}
EINA_VALUE_TYPE_DISPATCH(type, flush, EINA_ERROR_VALUE_FAILED, mem);
if (type->value_size > 8) free(mem);
if (type->value_size > 8)
eina_value_inner_free(type->value_size, mem);
value->type = NULL;
}

View File

@ -342,9 +342,9 @@ struct _Eina_Value
* On failure, @c NULL is returned and either #EINA_ERROR_OUT_OF_MEMORY or
* #EINA_ERROR_VALUE_FAILED is set.
*
* @note this calls malloc and then uses eina_value_setup().
* Consider using eina_value_flush() and eina_value_setup() instead
* to avoid memory allocations.
* @note this calls creates from mempool and then uses
* eina_value_setup(). Consider using eina_value_flush() and
* eina_value_setup() instead to avoid memory allocations.
*
* @see eina_value_free()
*
@ -815,9 +815,9 @@ struct _Eina_Value_Array
* On failure, @c NULL is returned and #EINA_ERROR_OUT_OF_MEMORY or
* #EINA_ERROR_VALUE_FAILED is set.
*
* @note this calls malloc and then uses eina_value_array_setup().
* @see eina_value_free()
* @see eina_value_array_setup()
* @note this creates from mempool and then uses
* eina_value_array_setup(). @see eina_value_free() @see
* eina_value_array_setup()
*
* @since 1.2
*/
@ -1439,7 +1439,8 @@ struct _Eina_Value_List
* On failure, @c NULL is returned and #EINA_ERROR_OUT_OF_MEMORY or
* #EINA_ERROR_VALUE_FAILED is set.
*
* @note this calls malloc and then uses eina_value_list_setup().
* @note this creates from mempool and then uses
* eina_value_list_setup().
*
* @see eina_value_free()
* @see eina_value_list_setup()
@ -2054,7 +2055,8 @@ struct _Eina_Value_Hash
* On failure, @c NULL is returned and #EINA_ERROR_OUT_OF_MEMORY or
* #EINA_ERROR_VALUE_FAILED is set.
*
* @note this calls malloc and then uses eina_value_hash_setup().
* @note this creates from mempool and then uses
* eina_value_hash_setup().
*
* @see eina_value_free()
* @see eina_value_hash_setup()

View File

@ -54,6 +54,8 @@ void *alloca (size_t);
#include "eina_error.h"
#include "eina_log.h"
#include "eina_strbuf.h"
#include "eina_mempool.h"
#include "eina_lock.h"
/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
#include "eina_safety_checks.h"
@ -67,6 +69,10 @@ void *alloca (size_t);
* @cond LOCAL
*/
static Eina_Mempool *_eina_value_mp = NULL;
static Eina_Hash *_eina_value_inner_mps = NULL;
static Eina_Lock _eina_value_inner_mps_lock;
static char *_eina_value_mp_choice = NULL;
static int _eina_value_log_dom = -1;
#ifdef ERR
@ -3987,12 +3993,119 @@ static const Eina_Value_Blob_Operations _EINA_VALUE_BLOB_OPERATIONS_MALLOC = {
NULL
};
typedef struct _Eina_Value_Inner_Mp Eina_Value_Inner_Mp;
struct _Eina_Value_Inner_Mp
{
Eina_Mempool *mempool;
int references;
};
/**
* @endcond
*/
static const char EINA_ERROR_VALUE_FAILED_STR[] = "Value check failed.";
/**
*/
static inline void
_eina_value_inner_mp_dispose(int size, Eina_Value_Inner_Mp *imp)
{
EINA_SAFETY_ON_FALSE_RETURN(imp->references == 0);
eina_hash_del_by_key(_eina_value_inner_mps, &size);
eina_mempool_del(imp->mempool);
free(imp);
}
static inline Eina_Value_Inner_Mp *
_eina_value_inner_mp_get(int size)
{
Eina_Value_Inner_Mp *imp = eina_hash_find(_eina_value_inner_mps, &size);
if (imp) return imp;
imp = malloc(sizeof(Eina_Value_Inner_Mp));
if (!imp)
return NULL;
imp->references = 0;
imp->mempool = eina_mempool_add(_eina_value_mp_choice,
"Eina_Value_Inner_Mp", NULL, size, 128);
if (!imp->mempool)
{
free(imp);
return NULL;
}
if (!eina_hash_add(_eina_value_inner_mps, &size, imp))
{
eina_mempool_del(imp->mempool);
free(imp);
return NULL;
}
return imp;
}
static inline void *
_eina_value_inner_alloc_internal(int size)
{
Eina_Value_Inner_Mp *imp;
void *mem;
imp = _eina_value_inner_mp_get(size);
if (!imp) return NULL;
mem = eina_mempool_malloc(imp->mempool, size);
if (mem) imp->references++;
else if (imp->references == 0) _eina_value_inner_mp_dispose(size, imp);
return mem;
}
static inline void
_eina_value_inner_free_internal(int size, void *mem)
{
Eina_Value_Inner_Mp *imp = eina_hash_find(_eina_value_inner_mps, &size);
EINA_SAFETY_ON_NULL_RETURN(imp);
eina_mempool_free(imp->mempool, mem);
imp->references--;
if (imp->references > 0) return;
_eina_value_inner_mp_dispose(size, imp);
}
EAPI void *
eina_value_inner_alloc(size_t size)
{
void *mem;
if (size > 256) return malloc(size);
eina_lock_take(&_eina_value_inner_mps_lock);
mem = _eina_value_inner_alloc_internal(size);
eina_lock_release(&_eina_value_inner_mps_lock);
return mem;
}
EAPI void
eina_value_inner_free(size_t size, void *mem)
{
if (size > 256)
{
free(mem);
return;
}
eina_lock_take(&_eina_value_inner_mps_lock);
_eina_value_inner_free_internal(size, mem);
eina_lock_release(&_eina_value_inner_mps_lock);
}
/**
* @internal
* @brief Initialize the value module.
@ -4007,6 +4120,8 @@ static const char EINA_ERROR_VALUE_FAILED_STR[] = "Value check failed.";
Eina_Bool
eina_value_init(void)
{
const char *choice, *tmp;
_eina_value_log_dom = eina_log_domain_register("eina_value",
EINA_LOG_COLOR_DEFAULT);
if (_eina_value_log_dom < 0)
@ -4015,6 +4130,38 @@ eina_value_init(void)
return EINA_FALSE;
}
#ifdef EINA_DEFAULT_MEMPOOL
choice = "pass_through";
#else
choice = "chained_mempool";
#endif
tmp = getenv("EINA_MEMPOOL");
if (tmp && tmp[0])
choice = tmp;
if (choice)
_eina_value_mp_choice = strdup(choice);
_eina_value_mp = eina_mempool_add
(_eina_value_mp_choice, "value", NULL, sizeof(Eina_Value), 320);
if (!_eina_value_mp)
{
ERR("Mempool for value cannot be allocated in value init.");
goto on_init_fail_mp;
}
if (!eina_lock_new(&_eina_value_inner_mps_lock))
{
ERR("Cannot create lock in value init.");
goto on_init_fail_lock;
}
_eina_value_inner_mps = eina_hash_int32_new(NULL);
if (!_eina_value_inner_mps)
{
ERR("Cannot create hash for inner mempools in value init.");
goto on_init_fail_hash;
}
EINA_ERROR_VALUE_FAILED = eina_error_msg_static_register(
EINA_ERROR_VALUE_FAILED_STR);
@ -4048,6 +4195,17 @@ eina_value_init(void)
EINA_VALUE_BLOB_OPERATIONS_MALLOC = &_EINA_VALUE_BLOB_OPERATIONS_MALLOC;
return EINA_TRUE;
on_init_fail_hash:
eina_lock_free(&_eina_value_inner_mps_lock);
on_init_fail_lock:
eina_mempool_del(_eina_value_mp);
on_init_fail_mp:
free(_eina_value_mp_choice);
_eina_value_mp_choice = NULL;
eina_log_domain_unregister(_eina_value_log_dom);
_eina_value_log_dom = -1;
return EINA_FALSE;
}
/**
@ -4064,6 +4222,17 @@ eina_value_init(void)
Eina_Bool
eina_value_shutdown(void)
{
eina_lock_take(&_eina_value_inner_mps_lock);
if (eina_hash_population(_eina_value_inner_mps) != 0)
ERR("Cannot free eina_value internal memory pools -- still in use!");
else
eina_hash_free(_eina_value_inner_mps);
eina_lock_release(&_eina_value_inner_mps_lock);
eina_lock_free(&_eina_value_inner_mps_lock);
free(_eina_value_mp_choice);
_eina_value_mp_choice = NULL;
eina_mempool_del(_eina_value_mp);
eina_log_domain_unregister(_eina_value_log_dom);
_eina_value_log_dom = -1;
return EINA_TRUE;
@ -4114,7 +4283,7 @@ EAPI const unsigned int eina_prime_table[] =
EAPI Eina_Value *
eina_value_new(const Eina_Value_Type *type)
{
Eina_Value *value = malloc(sizeof(Eina_Value));
Eina_Value *value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));;
if (!value)
{
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
@ -4133,7 +4302,7 @@ eina_value_free(Eina_Value *value)
{
EINA_SAFETY_ON_NULL_RETURN(value);
eina_value_flush(value);
free(value);
eina_mempool_free(_eina_value_mp, value);
}