fix eina_cow issues. Closes T581, T527

This commit is contained in:
Boris Faure 2013-11-25 23:33:51 +01:00
parent 1cad4c2afe
commit f45618d15b
2 changed files with 37 additions and 38 deletions

View File

@ -80,7 +80,6 @@ struct _Eina_Cow_GC
Eina_Cow_Ptr *ref; Eina_Cow_Ptr *ref;
const void **dst; const void **dst;
}; };
struct _Eina_Cow struct _Eina_Cow
{ {
#ifdef EINA_COW_MAGIC_ON #ifdef EINA_COW_MAGIC_ON
@ -91,7 +90,7 @@ struct _Eina_Cow
Eina_Hash *match; Eina_Hash *match;
Eina_Mempool *pool; Eina_Mempool *pool;
const void *default_value; const Eina_Cow_Data *default_value;
unsigned int struct_size; unsigned int struct_size;
unsigned int total_size; unsigned int total_size;
@ -123,7 +122,7 @@ typedef int (*Eina_Cow_Hash)(const void *, int);
(((Eina_Cow_Ptr *)d) - 1) (((Eina_Cow_Ptr *)d) - 1)
#define EINA_COW_DATA_GET(d) \ #define EINA_COW_DATA_GET(d) \
((unsigned char *)(d + 1)) (((Eina_Cow_Ptr *)d) + 1)
static int _eina_cow_log_dom = -1; static int _eina_cow_log_dom = -1;
@ -142,8 +141,9 @@ static int _eina_cow_log_dom = -1;
#endif #endif
#define DBG(...) EINA_LOG_DOM_DBG(_eina_cow_log_dom, __VA_ARGS__) #define DBG(...) EINA_LOG_DOM_DBG(_eina_cow_log_dom, __VA_ARGS__)
static Eina_Mempool *gc_pool = NULL; static Eina_Mempool *gc_pool = NULL;
static inline int static inline int
_eina_cow_hash_gen(const void *key, int key_length, _eina_cow_hash_gen(const void *key, int key_length,
Eina_Cow_Hash hash, Eina_Cow_Hash hash,
@ -184,7 +184,7 @@ static int current_cow_size = 0;
static unsigned int static unsigned int
_eina_cow_length(const void *key EINA_UNUSED) _eina_cow_length(const void *key EINA_UNUSED)
{ {
/* nasty hack, has only gc need to access the hash, he will be in charge /* nasty hack, since only gc needs to access the hash, it will be in charge
of that global. access to the hash should be considered global. of that global. access to the hash should be considered global.
*/ */
return current_cow_size; return current_cow_size;
@ -254,26 +254,25 @@ _eina_cow_togc_add(Eina_Cow *cow,
} }
static void static void
_eina_cow_gc(Eina_Cow *cow, Eina_Cow_Ptr *ref, _eina_cow_gc(Eina_Cow *cow, Eina_Cow_GC *gc)
const Eina_Cow_Data **dst,
void *data)
{ {
void *match; Eina_Cow_Data *data;
Eina_Cow_Data *match;
ref->togc = EINA_FALSE; data = EINA_COW_DATA_GET(gc->ref);
current_cow_size = cow->struct_size; current_cow_size = cow->struct_size;
match = eina_hash_find(cow->match, data); match = eina_hash_find(cow->match, data);
if (match) if (match)
{ {
ref = EINA_COW_PTR_GET(match); Eina_Cow_Ptr *ref = EINA_COW_PTR_GET(match);
#ifndef NVALGRIND #ifndef NVALGRIND
VALGRIND_MAKE_MEM_DEFINED(ref, sizeof (*ref)); VALGRIND_MAKE_MEM_DEFINED(ref, sizeof (*ref));
#endif #endif
ref->refcount++; ref->refcount += gc->ref->refcount;
eina_cow_free(cow, dst); *gc->dst = match;
*dst = match; eina_cow_free(cow, (const Eina_Cow_Data**) &data);
#ifndef NVALGRIND #ifndef NVALGRIND
VALGRIND_MAKE_MEM_NOACCESS(ref, sizeof (*ref)); VALGRIND_MAKE_MEM_NOACCESS(ref, sizeof (*ref));
@ -282,7 +281,9 @@ _eina_cow_gc(Eina_Cow *cow, Eina_Cow_Ptr *ref,
else else
{ {
eina_hash_direct_add(cow->match, data, data); eina_hash_direct_add(cow->match, data, data);
ref->hashed = EINA_TRUE; gc->ref->hashed = EINA_TRUE;
gc->ref->togc = EINA_FALSE;
eina_hash_del(cow->togc, &gc->ref, gc);
} }
} }
@ -366,7 +367,7 @@ eina_cow_add(const char *name, unsigned int struct_size, unsigned int step, cons
_eina_cow_cmp, _eina_cow_cmp,
_eina_cow_hash32, _eina_cow_hash32,
NULL, NULL,
6); 6);
#endif #endif
if (gc) if (gc)
cow->togc = eina_hash_pointer_new(_eina_cow_gc_free); cow->togc = eina_hash_pointer_new(_eina_cow_gc_free);
@ -453,7 +454,7 @@ eina_cow_write(Eina_Cow *cow,
const Eina_Cow_Data * const *data) const Eina_Cow_Data * const *data)
{ {
Eina_Cow_Ptr *ref; Eina_Cow_Ptr *ref;
void *r; Eina_Cow_Data *r;
#ifdef EINA_COW_MAGIC_ON #ifdef EINA_COW_MAGIC_ON
EINA_COW_MAGIC_CHECK(cow); EINA_COW_MAGIC_CHECK(cow);
@ -484,8 +485,8 @@ eina_cow_write(Eina_Cow *cow,
} }
#endif #endif
if (cow->togc) if (cow->togc)
_eina_cow_hash_del(cow, *data, ref); _eina_cow_hash_del(cow, *data, ref);
#ifndef NVALGRIND #ifndef NVALGRIND
VALGRIND_MAKE_MEM_NOACCESS(ref, sizeof (*ref)); VALGRIND_MAKE_MEM_NOACCESS(ref, sizeof (*ref));
@ -509,7 +510,7 @@ eina_cow_write(Eina_Cow *cow,
r = EINA_COW_DATA_GET(ref); r = EINA_COW_DATA_GET(ref);
memcpy(r, *data, cow->struct_size); memcpy(r, *data, cow->struct_size);
*((void**) data) = r; *((Eina_Cow_Data**) data) = r;
end: end:
#ifndef NVALGRIND #ifndef NVALGRIND
@ -602,8 +603,8 @@ eina_cow_gc(Eina_Cow *cow)
{ {
Eina_Cow_GC *gc; Eina_Cow_GC *gc;
Eina_Iterator *it; Eina_Iterator *it;
void *data;
Eina_Bool r; Eina_Bool r;
Eina_Cow_Ptr *ref;
EINA_COW_MAGIC_CHECK(cow); EINA_COW_MAGIC_CHECK(cow);
@ -613,22 +614,20 @@ eina_cow_gc(Eina_Cow *cow)
it = eina_hash_iterator_data_new(cow->togc); it = eina_hash_iterator_data_new(cow->togc);
r = eina_iterator_next(it, (void**) &gc); r = eina_iterator_next(it, (void**) &gc);
eina_iterator_free(it); eina_iterator_free(it);
if (!r) return EINA_FALSE; /* Something did go wrong here */ if (!r) return EINA_FALSE; /* Something did go wrong here */
/* Do handle hash and all funky merge think here */ /* Do handle hash and all funky merge thing here */
data = EINA_COW_DATA_GET(gc->ref); ref = gc->ref;
#ifndef NVALGRIND #ifndef NVALGRIND
VALGRIND_MAKE_MEM_DEFINED(gc->ref, sizeof (Eina_Cow_Ptr)); VALGRIND_MAKE_MEM_DEFINED(ref, sizeof (*ref));
#endif #endif
_eina_cow_gc(cow, gc->ref, gc->dst, data); _eina_cow_gc(cow, gc);
#ifndef NVALGRIND #ifndef NVALGRIND
VALGRIND_MAKE_MEM_NOACCESS(gc->ref, sizeof (Eina_Cow_Ptr)); VALGRIND_MAKE_MEM_NOACCESS(ref, sizeof (*ref));
#endif #endif
eina_hash_del(cow->togc, &gc->ref, gc);
return EINA_TRUE; return EINA_TRUE;
} }

View File

@ -56,9 +56,9 @@ typedef void Eina_Cow_Data;
* *
* @param name The name of this pool, used for debug. * @param name The name of this pool, used for debug.
* @param struct_size The size of the object from this pool. * @param struct_size The size of the object from this pool.
* @param step How many object to allocate when the pool get empty. * @param step How many objects to allocate when the pool gets empty.
* @param default_value The default value returned by this pool. * @param default_value The default value returned by this pool.
* @param gc Is it possible to run the garbage collection on this pool. * @param gc Is it possible to run garbage collection on this pool.
* @return a valid new Eina_Cow or @c NULL on error. * @return a valid new Eina_Cow or @c NULL on error.
*/ */
EAPI Eina_Cow *eina_cow_add(const char *name, unsigned int struct_size, unsigned int step, const void *default_value, Eina_Bool gc) EINA_WARN_UNUSED_RESULT; EAPI Eina_Cow *eina_cow_add(const char *name, unsigned int struct_size, unsigned int step, const void *default_value, Eina_Bool gc) EINA_WARN_UNUSED_RESULT;
@ -71,7 +71,7 @@ EAPI Eina_Cow *eina_cow_add(const char *name, unsigned int struct_size, unsigned
EAPI void eina_cow_del(Eina_Cow *cow); EAPI void eina_cow_del(Eina_Cow *cow);
/** /**
* @brief Return a initialized pointer to the pool. * @brief Return an initialized pointer from the pool.
* @param cow The pool to take things from. * @param cow The pool to take things from.
*/ */
EAPI const Eina_Cow_Data *eina_cow_alloc(Eina_Cow *cow) EINA_WARN_UNUSED_RESULT; EAPI const Eina_Cow_Data *eina_cow_alloc(Eina_Cow *cow) EINA_WARN_UNUSED_RESULT;
@ -98,8 +98,8 @@ EAPI void *eina_cow_write(Eina_Cow *cow,
/** /**
* @brief Set back a pointer into read only. * @brief Set back a pointer into read only.
* @param cow The pool the pointer come from. * @param cow The pool the pointer come from.
* @param src The read only version of the pointer. * @param dst The read only version of the pointer.
* @param data The pointer to which data where written to. * @param data The pointer to which data was written to.
* *
* NOTE: this function is not thread safe, be careful. * NOTE: this function is not thread safe, be careful.
*/ */
@ -118,13 +118,13 @@ EAPI void eina_cow_memcpy(Eina_Cow *cow,
const Eina_Cow_Data *src); const Eina_Cow_Data *src);
/** /**
* @brief Try to find entry that do have the same content and update them. * @brief Try to find entries that have the same content and update them.
* @param cow The cow to try to compact. * @param cow The cow to try to compact.
* @return EINA_TRUE if something was compacted, EINA_FALSE if nothing was. * @return EINA_TRUE if something was compacted, EINA_FALSE if nothing was.
* *
* There is no guaranty in the time it will require, but should remain low. * There is no guaranty in the time it will require, but should remain low.
* It does run a hash function on all possible common structure trying to * It does run a hash function on all possible common structures trying to
* find the one that match and merge then into one pointer. * find the one that match and merge them into one pointer.
*/ */
EAPI Eina_Bool eina_cow_gc(Eina_Cow *cow); EAPI Eina_Bool eina_cow_gc(Eina_Cow *cow);
@ -137,7 +137,7 @@ EAPI Eina_Bool eina_cow_gc(Eina_Cow *cow);
* @param Write The name of the variable where to put the writeable pointer to. * @param Write The name of the variable where to put the writeable pointer to.
* @since 1.8.0 * @since 1.8.0
* *
* Be careful this macro open a C scope that it expect to be closed by * Be careful this macro opens a C scope that is expected to be closed by
* EINA_COW_WRITE_END(). * EINA_COW_WRITE_END().
*/ */
#define EINA_COW_WRITE_BEGIN(Cow, Read, Write_Type, Write) \ #define EINA_COW_WRITE_BEGIN(Cow, Read, Write_Type, Write) \