summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@free.fr>2009-11-05 17:38:51 +0000
committerCedric BAIL <cedric.bail@free.fr>2009-11-05 17:38:51 +0000
commita82d161c277fef3ebaa97999c00c2ebd0bc894b3 (patch)
tree0c2ac3df40c7a267c4173b5d12c3ea29f612ff90
parentbf871d09755659575f374f338d00519fe2d5f7c3 (diff)
* evas_cache_image: Attempt to make a definitiv fix for race condition on cancel.
WARNING: If you continue to see any segv in E17, please report to me with a backtrace. Thanks. SVN revision: 43465
-rw-r--r--legacy/evas/src/lib/cache/evas_cache_image.c218
-rw-r--r--legacy/evas/src/lib/include/evas_common.h1
2 files changed, 121 insertions, 98 deletions
diff --git a/legacy/evas/src/lib/cache/evas_cache_image.c b/legacy/evas/src/lib/cache/evas_cache_image.c
index 19ea6d35d2..9959b2ad27 100644
--- a/legacy/evas/src/lib/cache/evas_cache_image.c
+++ b/legacy/evas/src/lib/cache/evas_cache_image.c
@@ -42,12 +42,15 @@ static pthread_cond_t cond_done = PTHREAD_COND_INITIALIZER;
42static pthread_cond_t cond_new = PTHREAD_COND_INITIALIZER; 42static pthread_cond_t cond_new = PTHREAD_COND_INITIALIZER;
43static pthread_mutex_t mutex_new = PTHREAD_MUTEX_INITIALIZER; 43static pthread_mutex_t mutex_new = PTHREAD_MUTEX_INITIALIZER;
44static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 44static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
45static pthread_mutex_t mutex_pending = PTHREAD_MUTEX_INITIALIZER;
45static pthread_mutex_t mutex_surface_alloc = PTHREAD_MUTEX_INITIALIZER; 46static pthread_mutex_t mutex_surface_alloc = PTHREAD_MUTEX_INITIALIZER;
46static pthread_t tid = 0; 47static pthread_t tid = 0;
47 48
48static Eina_Bool running = EINA_FALSE; 49static Eina_Bool running = EINA_FALSE;
49 50
50static void *_evas_cache_background_load(void *); 51static void *_evas_cache_background_load(void *);
52static void _evas_cache_image_entry_clear_preloaders(Image_Entry *ie);
53static int _evas_cache_image_entry_preload_remove(Image_Entry *ie, const void *target);
51#endif 54#endif
52 55
53#define FREESTRC(Var) \ 56#define FREESTRC(Var) \
@@ -186,6 +189,10 @@ _evas_cache_image_entry_delete(Evas_Cache_Image *cache, Image_Entry *ie)
186 if (cache->func.debug) 189 if (cache->func.debug)
187 cache->func.debug("deleting", ie); 190 cache->func.debug("deleting", ie);
188 191
192#ifdef BUILD_ASYNC_PRELOAD
193 _evas_cache_image_entry_preload_remove(ie, NULL);
194#endif
195
189 cache->func.destructor(ie); 196 cache->func.destructor(ie);
190 197
191 _evas_cache_image_remove_activ(cache, ie); 198 _evas_cache_image_remove_activ(cache, ie);
@@ -323,20 +330,37 @@ _evas_cache_image_entry_surface_alloc(Evas_Cache_Image *cache,
323 330
324#ifdef BUILD_ASYNC_PRELOAD 331#ifdef BUILD_ASYNC_PRELOAD
325static void 332static void
326_evas_cache_image_async_call__locked(Image_Entry *im) 333_evas_cache_image_async_call_process(void *obj, Evas_Callback_Type type, void *data)
327{ 334{
328 while (im->targets) 335 Image_Entry *ie = (Image_Entry *) obj;
336
337 ie->flags.in_pipe = 0;
338 while (ie->targets)
329 { 339 {
330 Evas_Cache_Target *tmp = im->targets; 340 Evas_Cache_Target *tmp = ie->targets;
331 341
332 evas_async_events_put(tmp->target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL, 342 evas_object_event_callback_call((Evas_Object*) tmp->target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL);
333 (void (*)(void*, Evas_Callback_Type, void*))evas_object_event_callback_call); 343 ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(ie->targets));
334 im->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(im->targets), EINA_INLIST_GET(im->targets));
335 free(tmp); 344 free(tmp);
336 } 345 }
337} 346}
338 347
339static void 348static void
349_evas_cache_image_entry_clear_preloaders(Image_Entry *ie)
350{
351 ie->flags.preload = 0;
352 ie->flags.in_pipe = 0;
353 evas_async_target_del(ie);
354}
355
356static void
357_evas_cache_image_async_call__locked(Image_Entry *im)
358{
359 evas_async_events_put(im, EVAS_CALLBACK_IMAGE_PRELOADED, NULL,
360 _evas_cache_image_async_call_process);
361}
362
363static void
340_evas_cache_image_async_call(Image_Entry *im) 364_evas_cache_image_async_call(Image_Entry *im)
341{ 365{
342 pthread_mutex_lock(&mutex); 366 pthread_mutex_lock(&mutex);
@@ -408,69 +432,70 @@ _evas_cache_image_entry_preload_remove(Image_Entry *ie, const void *target)
408{ 432{
409 int ret = 0; 433 int ret = 0;
410 434
411 if (running) 435 pthread_mutex_lock(&mutex);
436 if (target)
412 { 437 {
413 pthread_mutex_lock(&mutex); 438 Evas_Cache_Target *tg;
414 if (target) evas_async_target_del(target); 439
415 if (ie->flags.preload) 440 EINA_INLIST_FOREACH(ie->targets, tg)
416 { 441 {
417 if (current == ie) 442 if (tg->target == target)
418 { 443 {
444 // FIXME: No callback when we cancel only for one target ?
445 ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
446 free(tg);
447 break;
448 }
449 }
450 }
451
452 if (ie->flags.in_pipe)
453 {
454 if (!ie->targets)
455 _evas_cache_image_entry_clear_preloaders(ie);
456 }
457 else if (ie->flags.preload)
458 {
459 if (current == ie)
460 {
419// dont wait. simply handle "ie->flags.preload" nicely 461// dont wait. simply handle "ie->flags.preload" nicely
420// /* Wait until ie is processed. */ 462// /* Wait until ie is processed. */
421// pthread_cond_wait(&cond_done, &mutex); 463// pthread_cond_wait(&cond_done, &mutex);
422 } 464 }
423 else 465 else
466 {
467 Evas_Cache_Preload *l;
468
469 EINA_INLIST_FOREACH(preload, l)
424 { 470 {
425 Evas_Cache_Preload *l; 471 if (l->ie == ie)
426
427 EINA_INLIST_FOREACH(preload, l)
428 { 472 {
429 if (l->ie == ie) 473 if (target)
430 { 474 {
431 Evas_Cache_Target *tg; 475 // FIXME: No callback when we cancel only for one target ?
432
433 if (target)
434 {
435 EINA_INLIST_FOREACH(ie->targets, tg)
436 {
437 if (tg->target == target)
438 {
439 ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
440 free(tg);
441 break;
442 }
443 }
444 }
445 else
446 {
447 _evas_cache_image_async_call__locked(ie);
448
449 while (ie->targets)
450 {
451 tg = ie->targets;
452 evas_async_target_del(tg->target);
453 ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
454 free(tg);
455 }
456 }
457
458 if (!ie->targets) 476 if (!ie->targets)
459 { 477 _evas_cache_image_entry_clear_preloaders(ie);
460 preload = eina_inlist_remove(preload, 478 }
461 EINA_INLIST_GET(l)); 479 else
462 free(l); 480 {
463 } 481 _evas_cache_image_async_call__locked(ie);
464
465 break;
466 } 482 }
483
484 if (!ie->targets)
485 {
486 ie->flags.preload = 0;
487 preload = eina_inlist_remove(preload,
488 EINA_INLIST_GET(l));
489 free(l);
490 }
491
492 break;
467 } 493 }
468 ie->flags.preload = 0;
469 ret = 1;
470 } 494 }
495 ret = 1;
471 } 496 }
472 pthread_mutex_unlock(&mutex);
473 } 497 }
498 pthread_mutex_unlock(&mutex);
474 499
475 return ret; 500 return ret;
476} 501}
@@ -523,9 +548,12 @@ _evas_cache_background_load(void *data)
523 } 548 }
524 549
525 pthread_mutex_lock(&mutex); 550 pthread_mutex_lock(&mutex);
551 pthread_mutex_lock(&mutex_pending);
526 current->flags.preload = 0; 552 current->flags.preload = 0;
553 current->flags.in_pipe = 1;
527 current->channel = pchannel; 554 current->channel = pchannel;
528 LKU(current->lock); 555 LKU(current->lock);
556 pthread_mutex_unlock(&mutex_pending);
529 pthread_mutex_unlock(&mutex); 557 pthread_mutex_unlock(&mutex);
530 558
531 _evas_cache_image_async_call(current); 559 _evas_cache_image_async_call(current);
@@ -617,21 +645,6 @@ _evas_cache_image_free_cb(__UNUSED__ const Eina_Hash *hash, __UNUSED__ const voi
617 return EINA_TRUE; 645 return EINA_TRUE;
618} 646}
619 647
620#ifdef BUILD_ASYNC_PRELOAD
621static void
622_evas_cache_image_entry_clear_preloaders(Image_Entry *ie)
623{
624 while (ie->targets)
625 {
626 Evas_Cache_Target *t = ie->targets;
627 ie->targets = (Evas_Cache_Target *)
628 eina_inlist_remove(EINA_INLIST_GET(ie->targets),
629 EINA_INLIST_GET(ie->targets));
630 free(t);
631 }
632}
633#endif
634
635EAPI void 648EAPI void
636evas_cache_image_shutdown(Evas_Cache_Image *cache) 649evas_cache_image_shutdown(Evas_Cache_Image *cache)
637{ 650{
@@ -646,24 +659,25 @@ evas_cache_image_shutdown(Evas_Cache_Image *cache)
646 659
647#ifdef BUILD_ASYNC_PRELOAD 660#ifdef BUILD_ASYNC_PRELOAD
648 pthread_mutex_lock(&mutex); 661 pthread_mutex_lock(&mutex);
649 if (running) 662
663 Eina_Inlist *l, *l_next;
664 for (l = preload; l != NULL; l = l_next)
650 { 665 {
651 Eina_Inlist *l, *l_next; 666 Evas_Cache_Preload *tmp = (Evas_Cache_Preload *)l;
652 for (l = preload; l != NULL; l = l_next) 667 Image_Entry *ie = tmp->ie;
653 {
654 Evas_Cache_Preload *tmp = (Evas_Cache_Preload *)l;
655 Image_Entry *ie = tmp->ie;
656 668
657 l_next = l->next; 669 l_next = l->next;
658 670
659 if (ie->cache != cache) 671 if (ie->cache != cache)
660 continue; 672 continue;
661 673
662 preload = eina_inlist_remove(preload, l); 674 preload = eina_inlist_remove(preload, l);
663 _evas_cache_image_entry_clear_preloaders(ie); 675 _evas_cache_image_entry_clear_preloaders(ie);
664 free(l); 676 free(l);
665 }
666 } 677 }
678
679 if (current && current->cache == cache)
680 _evas_cache_image_entry_clear_preloaders(current);
667 pthread_mutex_unlock(&mutex); 681 pthread_mutex_unlock(&mutex);
668#endif 682#endif
669 683
@@ -881,7 +895,7 @@ evas_cache_pending_process(void)
881 Image_Entry *im; 895 Image_Entry *im;
882 896
883#ifdef BUILD_ASYNC_PRELOAD 897#ifdef BUILD_ASYNC_PRELOAD
884 pthread_mutex_lock(&mutex); 898 pthread_mutex_lock(&mutex_pending);
885 EINA_LIST_FREE(pending, im) 899 EINA_LIST_FREE(pending, im)
886 { 900 {
887 Evas_Cache_Image *cache = im->cache; 901 Evas_Cache_Image *cache = im->cache;
@@ -908,7 +922,7 @@ evas_cache_pending_process(void)
908 evas_cache_image_flush(cache); 922 evas_cache_image_flush(cache);
909 } 923 }
910 } 924 }
911 pthread_mutex_unlock(&mutex); 925 pthread_mutex_unlock(&mutex_pending);
912#endif 926#endif
913} 927}
914 928
@@ -923,27 +937,24 @@ evas_cache_image_drop(Image_Entry *im)
923 im->references--; 937 im->references--;
924 cache = im->cache; 938 cache = im->cache;
925 939
926 if (im->references == 0) 940 if (im->references == 0 && !im->flags.pending)
927 { 941 {
928#ifdef BUILD_ASYNC_PRELOAD 942#ifdef BUILD_ASYNC_PRELOAD
929 _evas_cache_image_entry_preload_remove(im, NULL);
930 /*
931 pthread_mutex_lock(&mutex); 943 pthread_mutex_lock(&mutex);
932 if (im->flags.preload) 944 if (im->flags.preload || im->flags.in_pipe)
933 { 945 {
934 pthread_mutex_unlock(&mutex); 946 pthread_mutex_unlock(&mutex);
935 _evas_cache_image_entry_preload_remove(im, NULL); 947 _evas_cache_image_entry_preload_remove(im, NULL);
936 pthread_mutex_lock(&mutex); 948 pthread_mutex_lock(&mutex_pending);
937 if (!im->flags.pending) 949 if (!im->flags.pending)
938 { 950 {
939 im->flags.pending = 1; 951 im->flags.pending = 1;
940 pending = eina_list_append(pending, im); 952 pending = eina_list_append(pending, im);
941 } 953 }
942 pthread_mutex_unlock(&mutex); 954 pthread_mutex_unlock(&mutex_pending);
943 return; 955 return;
944 } 956 }
945 pthread_mutex_unlock(&mutex); 957 pthread_mutex_unlock(&mutex);
946 */
947#endif 958#endif
948 959
949 if (im->flags.dirty) 960 if (im->flags.dirty)
@@ -1233,7 +1244,10 @@ evas_cache_image_load_data(Image_Entry *im)
1233 assert(im->cache); 1244 assert(im->cache);
1234 cache = im->cache; 1245 cache = im->cache;
1235 1246
1236 if (im->flags.loaded) return; 1247 if (im->flags.loaded)
1248 {
1249 return;
1250 }
1237#ifdef BUILD_ASYNC_PRELOAD 1251#ifdef BUILD_ASYNC_PRELOAD
1238 pthread_mutex_lock(&mutex); 1252 pthread_mutex_lock(&mutex);
1239 preload = im->flags.preload; 1253 preload = im->flags.preload;
@@ -1285,21 +1299,18 @@ evas_cache_image_preload_data(Image_Entry *im, const void *target)
1285 1299
1286 if (im->flags.loaded) 1300 if (im->flags.loaded)
1287 { 1301 {
1288 evas_async_events_put(target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL, 1302 evas_object_event_callback_call((Evas_Object*) target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL);
1289 (void (*)(void*, Evas_Callback_Type, void*))evas_object_event_callback_call);
1290 return ; 1303 return ;
1291 } 1304 }
1292 1305
1293 cache = im->cache; 1306 cache = im->cache;
1294 1307
1295 if (!_evas_cache_image_entry_preload_add(im, target)) 1308 if (!_evas_cache_image_entry_preload_add(im, target))
1296 evas_async_events_put(target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL, 1309 evas_object_event_callback_call((Evas_Object*) target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL);
1297 (void (*)(void*, Evas_Callback_Type, void*))evas_object_event_callback_call);
1298#else 1310#else
1299 evas_cache_image_load_data(im); 1311 evas_cache_image_load_data(im);
1300 1312
1301 evas_async_events_put(target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL, 1313 evas_object_event_callback_call((Evas_Object*) target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL);
1302 (void (*)(void*, Evas_Callback_Type, void*))evas_object_event_callback_call);
1303#endif 1314#endif
1304} 1315}
1305 1316
@@ -1313,7 +1324,18 @@ evas_cache_image_preload_cancel(Image_Entry *im, const void *target)
1313 assert(im->cache); 1324 assert(im->cache);
1314 cache = im->cache; 1325 cache = im->cache;
1315 1326
1327 if (target == NULL) return ;
1328
1316 _evas_cache_image_entry_preload_remove(im, target); 1329 _evas_cache_image_entry_preload_remove(im, target);
1330
1331 pthread_mutex_lock(&mutex_pending);
1332 if (!im->flags.pending && im->flags.in_pipe)
1333 {
1334 im->flags.pending = 1;
1335 pending = eina_list_append(pending, im);
1336 }
1337 pthread_mutex_unlock(&mutex_pending);
1338
1317#else 1339#else
1318 (void) im; 1340 (void) im;
1319#endif 1341#endif
diff --git a/legacy/evas/src/lib/include/evas_common.h b/legacy/evas/src/lib/include/evas_common.h
index 377320ddb4..c869a80522 100644
--- a/legacy/evas/src/lib/include/evas_common.h
+++ b/legacy/evas/src/lib/include/evas_common.h
@@ -470,6 +470,7 @@ struct _Image_Entry_Flags
470#ifdef BUILD_ASYNC_PRELOAD 470#ifdef BUILD_ASYNC_PRELOAD
471 Eina_Bool preload : 1; 471 Eina_Bool preload : 1;
472 Eina_Bool pending : 1; 472 Eina_Bool pending : 1;
473 Eina_Bool in_pipe : 1;
473#endif 474#endif
474}; 475};
475 476