summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Faure <billiob@gmail.com>2013-11-25 23:33:51 +0100
committerBoris Faure <billiob@gmail.com>2013-11-30 15:41:08 +0100
commitf45618d15b00cf3619fd22df4459bb700cc25f70 (patch)
treede6a18eba4eee919cb506fe94de516f813172952
parent1cad4c2afecd274d9fc5d913ba1137f2bee55230 (diff)
fix eina_cow issues. Closes T581, T527
-rw-r--r--src/lib/eina/eina_cow.c57
-rw-r--r--src/lib/eina/eina_cow.h18
2 files changed, 37 insertions, 38 deletions
diff --git a/src/lib/eina/eina_cow.c b/src/lib/eina/eina_cow.c
index ca99f5c596..2b1a3e502f 100644
--- a/src/lib/eina/eina_cow.c
+++ b/src/lib/eina/eina_cow.c
@@ -80,7 +80,6 @@ struct _Eina_Cow_GC
80 Eina_Cow_Ptr *ref; 80 Eina_Cow_Ptr *ref;
81 const void **dst; 81 const void **dst;
82}; 82};
83
84struct _Eina_Cow 83struct _Eina_Cow
85{ 84{
86#ifdef EINA_COW_MAGIC_ON 85#ifdef EINA_COW_MAGIC_ON
@@ -91,7 +90,7 @@ struct _Eina_Cow
91 Eina_Hash *match; 90 Eina_Hash *match;
92 91
93 Eina_Mempool *pool; 92 Eina_Mempool *pool;
94 const void *default_value; 93 const Eina_Cow_Data *default_value;
95 94
96 unsigned int struct_size; 95 unsigned int struct_size;
97 unsigned int total_size; 96 unsigned int total_size;
@@ -123,7 +122,7 @@ typedef int (*Eina_Cow_Hash)(const void *, int);
123 (((Eina_Cow_Ptr *)d) - 1) 122 (((Eina_Cow_Ptr *)d) - 1)
124 123
125#define EINA_COW_DATA_GET(d) \ 124#define EINA_COW_DATA_GET(d) \
126 ((unsigned char *)(d + 1)) 125 (((Eina_Cow_Ptr *)d) + 1)
127 126
128static int _eina_cow_log_dom = -1; 127static int _eina_cow_log_dom = -1;
129 128
@@ -142,8 +141,9 @@ static int _eina_cow_log_dom = -1;
142#endif 141#endif
143#define DBG(...) EINA_LOG_DOM_DBG(_eina_cow_log_dom, __VA_ARGS__) 142#define DBG(...) EINA_LOG_DOM_DBG(_eina_cow_log_dom, __VA_ARGS__)
144 143
144
145static Eina_Mempool *gc_pool = NULL; 145static Eina_Mempool *gc_pool = NULL;
146 146
147static inline int 147static inline int
148_eina_cow_hash_gen(const void *key, int key_length, 148_eina_cow_hash_gen(const void *key, int key_length,
149 Eina_Cow_Hash hash, 149 Eina_Cow_Hash hash,
@@ -184,7 +184,7 @@ static int current_cow_size = 0;
184static unsigned int 184static unsigned int
185_eina_cow_length(const void *key EINA_UNUSED) 185_eina_cow_length(const void *key EINA_UNUSED)
186{ 186{
187 /* nasty hack, has only gc need to access the hash, he will be in charge 187 /* nasty hack, since only gc needs to access the hash, it will be in charge
188 of that global. access to the hash should be considered global. 188 of that global. access to the hash should be considered global.
189 */ 189 */
190 return current_cow_size; 190 return current_cow_size;
@@ -254,26 +254,25 @@ _eina_cow_togc_add(Eina_Cow *cow,
254} 254}
255 255
256static void 256static void
257_eina_cow_gc(Eina_Cow *cow, Eina_Cow_Ptr *ref, 257_eina_cow_gc(Eina_Cow *cow, Eina_Cow_GC *gc)
258 const Eina_Cow_Data **dst,
259 void *data)
260{ 258{
261 void *match; 259 Eina_Cow_Data *data;
260 Eina_Cow_Data *match;
262 261
263 ref->togc = EINA_FALSE; 262 data = EINA_COW_DATA_GET(gc->ref);
264 263
265 current_cow_size = cow->struct_size; 264 current_cow_size = cow->struct_size;
266 match = eina_hash_find(cow->match, data); 265 match = eina_hash_find(cow->match, data);
267 if (match) 266 if (match)
268 { 267 {
269 ref = EINA_COW_PTR_GET(match); 268 Eina_Cow_Ptr *ref = EINA_COW_PTR_GET(match);
270#ifndef NVALGRIND 269#ifndef NVALGRIND
271 VALGRIND_MAKE_MEM_DEFINED(ref, sizeof (*ref)); 270 VALGRIND_MAKE_MEM_DEFINED(ref, sizeof (*ref));
272#endif 271#endif
273 ref->refcount++; 272 ref->refcount += gc->ref->refcount;
274 273
275 eina_cow_free(cow, dst); 274 *gc->dst = match;
276 *dst = match; 275 eina_cow_free(cow, (const Eina_Cow_Data**) &data);
277 276
278#ifndef NVALGRIND 277#ifndef NVALGRIND
279 VALGRIND_MAKE_MEM_NOACCESS(ref, sizeof (*ref)); 278 VALGRIND_MAKE_MEM_NOACCESS(ref, sizeof (*ref));
@@ -282,7 +281,9 @@ _eina_cow_gc(Eina_Cow *cow, Eina_Cow_Ptr *ref,
282 else 281 else
283 { 282 {
284 eina_hash_direct_add(cow->match, data, data); 283 eina_hash_direct_add(cow->match, data, data);
285 ref->hashed = EINA_TRUE; 284 gc->ref->hashed = EINA_TRUE;
285 gc->ref->togc = EINA_FALSE;
286 eina_hash_del(cow->togc, &gc->ref, gc);
286 } 287 }
287} 288}
288 289
@@ -366,7 +367,7 @@ eina_cow_add(const char *name, unsigned int struct_size, unsigned int step, cons
366 _eina_cow_cmp, 367 _eina_cow_cmp,
367 _eina_cow_hash32, 368 _eina_cow_hash32,
368 NULL, 369 NULL,
369 6); 370 6);
370#endif 371#endif
371 if (gc) 372 if (gc)
372 cow->togc = eina_hash_pointer_new(_eina_cow_gc_free); 373 cow->togc = eina_hash_pointer_new(_eina_cow_gc_free);
@@ -453,7 +454,7 @@ eina_cow_write(Eina_Cow *cow,
453 const Eina_Cow_Data * const *data) 454 const Eina_Cow_Data * const *data)
454{ 455{
455 Eina_Cow_Ptr *ref; 456 Eina_Cow_Ptr *ref;
456 void *r; 457 Eina_Cow_Data *r;
457 458
458#ifdef EINA_COW_MAGIC_ON 459#ifdef EINA_COW_MAGIC_ON
459 EINA_COW_MAGIC_CHECK(cow); 460 EINA_COW_MAGIC_CHECK(cow);
@@ -484,8 +485,8 @@ eina_cow_write(Eina_Cow *cow,
484 } 485 }
485#endif 486#endif
486 487
487 if (cow->togc) 488 if (cow->togc)
488 _eina_cow_hash_del(cow, *data, ref); 489 _eina_cow_hash_del(cow, *data, ref);
489 490
490#ifndef NVALGRIND 491#ifndef NVALGRIND
491 VALGRIND_MAKE_MEM_NOACCESS(ref, sizeof (*ref)); 492 VALGRIND_MAKE_MEM_NOACCESS(ref, sizeof (*ref));
@@ -509,7 +510,7 @@ eina_cow_write(Eina_Cow *cow,
509 510
510 r = EINA_COW_DATA_GET(ref); 511 r = EINA_COW_DATA_GET(ref);
511 memcpy(r, *data, cow->struct_size); 512 memcpy(r, *data, cow->struct_size);
512 *((void**) data) = r; 513 *((Eina_Cow_Data**) data) = r;
513 514
514 end: 515 end:
515#ifndef NVALGRIND 516#ifndef NVALGRIND
@@ -602,8 +603,8 @@ eina_cow_gc(Eina_Cow *cow)
602{ 603{
603 Eina_Cow_GC *gc; 604 Eina_Cow_GC *gc;
604 Eina_Iterator *it; 605 Eina_Iterator *it;
605 void *data;
606 Eina_Bool r; 606 Eina_Bool r;
607 Eina_Cow_Ptr *ref;
607 608
608 EINA_COW_MAGIC_CHECK(cow); 609 EINA_COW_MAGIC_CHECK(cow);
609 610
@@ -613,22 +614,20 @@ eina_cow_gc(Eina_Cow *cow)
613 it = eina_hash_iterator_data_new(cow->togc); 614 it = eina_hash_iterator_data_new(cow->togc);
614 r = eina_iterator_next(it, (void**) &gc); 615 r = eina_iterator_next(it, (void**) &gc);
615 eina_iterator_free(it); 616 eina_iterator_free(it);
616 617
617 if (!r) return EINA_FALSE; /* Something did go wrong here */ 618 if (!r) return EINA_FALSE; /* Something did go wrong here */
618 619
619 /* Do handle hash and all funky merge think here */ 620 /* Do handle hash and all funky merge thing here */
620 data = EINA_COW_DATA_GET(gc->ref); 621 ref = gc->ref;
621 622
622#ifndef NVALGRIND 623#ifndef NVALGRIND
623 VALGRIND_MAKE_MEM_DEFINED(gc->ref, sizeof (Eina_Cow_Ptr)); 624 VALGRIND_MAKE_MEM_DEFINED(ref, sizeof (*ref));
624#endif 625#endif
625 _eina_cow_gc(cow, gc->ref, gc->dst, data); 626 _eina_cow_gc(cow, gc);
626#ifndef NVALGRIND 627#ifndef NVALGRIND
627 VALGRIND_MAKE_MEM_NOACCESS(gc->ref, sizeof (Eina_Cow_Ptr)); 628 VALGRIND_MAKE_MEM_NOACCESS(ref, sizeof (*ref));
628#endif 629#endif
629 630
630 eina_hash_del(cow->togc, &gc->ref, gc);
631
632 return EINA_TRUE; 631 return EINA_TRUE;
633} 632}
634 633
diff --git a/src/lib/eina/eina_cow.h b/src/lib/eina/eina_cow.h
index 10cb34d28d..bbbcf4b677 100644
--- a/src/lib/eina/eina_cow.h
+++ b/src/lib/eina/eina_cow.h
@@ -56,9 +56,9 @@ typedef void Eina_Cow_Data;
56 * 56 *
57 * @param name The name of this pool, used for debug. 57 * @param name The name of this pool, used for debug.
58 * @param struct_size The size of the object from this pool. 58 * @param struct_size The size of the object from this pool.
59 * @param step How many object to allocate when the pool get empty. 59 * @param step How many objects to allocate when the pool gets empty.
60 * @param default_value The default value returned by this pool. 60 * @param default_value The default value returned by this pool.
61 * @param gc Is it possible to run the garbage collection on this pool. 61 * @param gc Is it possible to run garbage collection on this pool.
62 * @return a valid new Eina_Cow or @c NULL on error. 62 * @return a valid new Eina_Cow or @c NULL on error.
63 */ 63 */
64EAPI 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; 64EAPI 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
71EAPI void eina_cow_del(Eina_Cow *cow); 71EAPI void eina_cow_del(Eina_Cow *cow);
72 72
73/** 73/**
74 * @brief Return a initialized pointer to the pool. 74 * @brief Return an initialized pointer from the pool.
75 * @param cow The pool to take things from. 75 * @param cow The pool to take things from.
76 */ 76 */
77EAPI const Eina_Cow_Data *eina_cow_alloc(Eina_Cow *cow) EINA_WARN_UNUSED_RESULT; 77EAPI 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,
98/** 98/**
99 * @brief Set back a pointer into read only. 99 * @brief Set back a pointer into read only.
100 * @param cow The pool the pointer come from. 100 * @param cow The pool the pointer come from.
101 * @param src The read only version of the pointer. 101 * @param dst The read only version of the pointer.
102 * @param data The pointer to which data where written to. 102 * @param data The pointer to which data was written to.
103 * 103 *
104 * NOTE: this function is not thread safe, be careful. 104 * NOTE: this function is not thread safe, be careful.
105 */ 105 */
@@ -118,13 +118,13 @@ EAPI void eina_cow_memcpy(Eina_Cow *cow,
118 const Eina_Cow_Data *src); 118 const Eina_Cow_Data *src);
119 119
120/** 120/**
121 * @brief Try to find entry that do have the same content and update them. 121 * @brief Try to find entries that have the same content and update them.
122 * @param cow The cow to try to compact. 122 * @param cow The cow to try to compact.
123 * @return EINA_TRUE if something was compacted, EINA_FALSE if nothing was. 123 * @return EINA_TRUE if something was compacted, EINA_FALSE if nothing was.
124 * 124 *
125 * There is no guaranty in the time it will require, but should remain low. 125 * There is no guaranty in the time it will require, but should remain low.
126 * It does run a hash function on all possible common structure trying to 126 * It does run a hash function on all possible common structures trying to
127 * find the one that match and merge then into one pointer. 127 * find the one that match and merge them into one pointer.
128 */ 128 */
129EAPI Eina_Bool eina_cow_gc(Eina_Cow *cow); 129EAPI Eina_Bool eina_cow_gc(Eina_Cow *cow);
130 130
@@ -137,7 +137,7 @@ EAPI Eina_Bool eina_cow_gc(Eina_Cow *cow);
137 * @param Write The name of the variable where to put the writeable pointer to. 137 * @param Write The name of the variable where to put the writeable pointer to.
138 * @since 1.8.0 138 * @since 1.8.0
139 * 139 *
140 * Be careful this macro open a C scope that it expect to be closed by 140 * Be careful this macro opens a C scope that is expected to be closed by
141 * EINA_COW_WRITE_END(). 141 * EINA_COW_WRITE_END().
142 */ 142 */
143#define EINA_COW_WRITE_BEGIN(Cow, Read, Write_Type, Write) \ 143#define EINA_COW_WRITE_BEGIN(Cow, Read, Write_Type, Write) \