forked from enlightenment/efl
eina_value: use mempool.
thanks to discomfitor about the tip. SVN revision: 67151
This commit is contained in:
parent
90e2259b6f
commit
9d424b133b
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue