forked from enlightenment/efl
* 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
This commit is contained in:
parent
bf871d0975
commit
a82d161c27
|
@ -42,12 +42,15 @@ static pthread_cond_t cond_done = PTHREAD_COND_INITIALIZER;
|
||||||
static pthread_cond_t cond_new = PTHREAD_COND_INITIALIZER;
|
static pthread_cond_t cond_new = PTHREAD_COND_INITIALIZER;
|
||||||
static pthread_mutex_t mutex_new = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t mutex_new = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static pthread_mutex_t mutex_pending = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static pthread_mutex_t mutex_surface_alloc = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t mutex_surface_alloc = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static pthread_t tid = 0;
|
static pthread_t tid = 0;
|
||||||
|
|
||||||
static Eina_Bool running = EINA_FALSE;
|
static Eina_Bool running = EINA_FALSE;
|
||||||
|
|
||||||
static void *_evas_cache_background_load(void *);
|
static void *_evas_cache_background_load(void *);
|
||||||
|
static void _evas_cache_image_entry_clear_preloaders(Image_Entry *ie);
|
||||||
|
static int _evas_cache_image_entry_preload_remove(Image_Entry *ie, const void *target);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FREESTRC(Var) \
|
#define FREESTRC(Var) \
|
||||||
|
@ -186,6 +189,10 @@ _evas_cache_image_entry_delete(Evas_Cache_Image *cache, Image_Entry *ie)
|
||||||
if (cache->func.debug)
|
if (cache->func.debug)
|
||||||
cache->func.debug("deleting", ie);
|
cache->func.debug("deleting", ie);
|
||||||
|
|
||||||
|
#ifdef BUILD_ASYNC_PRELOAD
|
||||||
|
_evas_cache_image_entry_preload_remove(ie, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
cache->func.destructor(ie);
|
cache->func.destructor(ie);
|
||||||
|
|
||||||
_evas_cache_image_remove_activ(cache, ie);
|
_evas_cache_image_remove_activ(cache, ie);
|
||||||
|
@ -323,19 +330,36 @@ _evas_cache_image_entry_surface_alloc(Evas_Cache_Image *cache,
|
||||||
|
|
||||||
#ifdef BUILD_ASYNC_PRELOAD
|
#ifdef BUILD_ASYNC_PRELOAD
|
||||||
static void
|
static void
|
||||||
_evas_cache_image_async_call__locked(Image_Entry *im)
|
_evas_cache_image_async_call_process(void *obj, Evas_Callback_Type type, void *data)
|
||||||
{
|
{
|
||||||
while (im->targets)
|
Image_Entry *ie = (Image_Entry *) obj;
|
||||||
{
|
|
||||||
Evas_Cache_Target *tmp = im->targets;
|
|
||||||
|
|
||||||
evas_async_events_put(tmp->target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL,
|
ie->flags.in_pipe = 0;
|
||||||
(void (*)(void*, Evas_Callback_Type, void*))evas_object_event_callback_call);
|
while (ie->targets)
|
||||||
im->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(im->targets), EINA_INLIST_GET(im->targets));
|
{
|
||||||
|
Evas_Cache_Target *tmp = ie->targets;
|
||||||
|
|
||||||
|
evas_object_event_callback_call((Evas_Object*) tmp->target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL);
|
||||||
|
ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(ie->targets));
|
||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_evas_cache_image_entry_clear_preloaders(Image_Entry *ie)
|
||||||
|
{
|
||||||
|
ie->flags.preload = 0;
|
||||||
|
ie->flags.in_pipe = 0;
|
||||||
|
evas_async_target_del(ie);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_evas_cache_image_async_call__locked(Image_Entry *im)
|
||||||
|
{
|
||||||
|
evas_async_events_put(im, EVAS_CALLBACK_IMAGE_PRELOADED, NULL,
|
||||||
|
_evas_cache_image_async_call_process);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_evas_cache_image_async_call(Image_Entry *im)
|
_evas_cache_image_async_call(Image_Entry *im)
|
||||||
{
|
{
|
||||||
|
@ -408,69 +432,70 @@ _evas_cache_image_entry_preload_remove(Image_Entry *ie, const void *target)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (running)
|
pthread_mutex_lock(&mutex);
|
||||||
|
if (target)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
Evas_Cache_Target *tg;
|
||||||
if (target) evas_async_target_del(target);
|
|
||||||
if (ie->flags.preload)
|
EINA_INLIST_FOREACH(ie->targets, tg)
|
||||||
{
|
{
|
||||||
if (current == ie)
|
if (tg->target == target)
|
||||||
{
|
{
|
||||||
|
// FIXME: No callback when we cancel only for one target ?
|
||||||
|
ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
|
||||||
|
free(tg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ie->flags.in_pipe)
|
||||||
|
{
|
||||||
|
if (!ie->targets)
|
||||||
|
_evas_cache_image_entry_clear_preloaders(ie);
|
||||||
|
}
|
||||||
|
else if (ie->flags.preload)
|
||||||
|
{
|
||||||
|
if (current == ie)
|
||||||
|
{
|
||||||
// dont wait. simply handle "ie->flags.preload" nicely
|
// dont wait. simply handle "ie->flags.preload" nicely
|
||||||
// /* Wait until ie is processed. */
|
// /* Wait until ie is processed. */
|
||||||
// pthread_cond_wait(&cond_done, &mutex);
|
// pthread_cond_wait(&cond_done, &mutex);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Evas_Cache_Preload *l;
|
|
||||||
|
|
||||||
EINA_INLIST_FOREACH(preload, l)
|
|
||||||
{
|
|
||||||
if (l->ie == ie)
|
|
||||||
{
|
|
||||||
Evas_Cache_Target *tg;
|
|
||||||
|
|
||||||
if (target)
|
|
||||||
{
|
|
||||||
EINA_INLIST_FOREACH(ie->targets, tg)
|
|
||||||
{
|
|
||||||
if (tg->target == target)
|
|
||||||
{
|
|
||||||
ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
|
|
||||||
free(tg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_evas_cache_image_async_call__locked(ie);
|
|
||||||
|
|
||||||
while (ie->targets)
|
|
||||||
{
|
|
||||||
tg = ie->targets;
|
|
||||||
evas_async_target_del(tg->target);
|
|
||||||
ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
|
|
||||||
free(tg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ie->targets)
|
|
||||||
{
|
|
||||||
preload = eina_inlist_remove(preload,
|
|
||||||
EINA_INLIST_GET(l));
|
|
||||||
free(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ie->flags.preload = 0;
|
|
||||||
ret = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
else
|
||||||
|
{
|
||||||
|
Evas_Cache_Preload *l;
|
||||||
|
|
||||||
|
EINA_INLIST_FOREACH(preload, l)
|
||||||
|
{
|
||||||
|
if (l->ie == ie)
|
||||||
|
{
|
||||||
|
if (target)
|
||||||
|
{
|
||||||
|
// FIXME: No callback when we cancel only for one target ?
|
||||||
|
if (!ie->targets)
|
||||||
|
_evas_cache_image_entry_clear_preloaders(ie);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_evas_cache_image_async_call__locked(ie);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ie->targets)
|
||||||
|
{
|
||||||
|
ie->flags.preload = 0;
|
||||||
|
preload = eina_inlist_remove(preload,
|
||||||
|
EINA_INLIST_GET(l));
|
||||||
|
free(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -523,9 +548,12 @@ _evas_cache_background_load(void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_lock(&mutex);
|
||||||
|
pthread_mutex_lock(&mutex_pending);
|
||||||
current->flags.preload = 0;
|
current->flags.preload = 0;
|
||||||
|
current->flags.in_pipe = 1;
|
||||||
current->channel = pchannel;
|
current->channel = pchannel;
|
||||||
LKU(current->lock);
|
LKU(current->lock);
|
||||||
|
pthread_mutex_unlock(&mutex_pending);
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
|
|
||||||
_evas_cache_image_async_call(current);
|
_evas_cache_image_async_call(current);
|
||||||
|
@ -617,21 +645,6 @@ _evas_cache_image_free_cb(__UNUSED__ const Eina_Hash *hash, __UNUSED__ const voi
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BUILD_ASYNC_PRELOAD
|
|
||||||
static void
|
|
||||||
_evas_cache_image_entry_clear_preloaders(Image_Entry *ie)
|
|
||||||
{
|
|
||||||
while (ie->targets)
|
|
||||||
{
|
|
||||||
Evas_Cache_Target *t = ie->targets;
|
|
||||||
ie->targets = (Evas_Cache_Target *)
|
|
||||||
eina_inlist_remove(EINA_INLIST_GET(ie->targets),
|
|
||||||
EINA_INLIST_GET(ie->targets));
|
|
||||||
free(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EAPI void
|
EAPI void
|
||||||
evas_cache_image_shutdown(Evas_Cache_Image *cache)
|
evas_cache_image_shutdown(Evas_Cache_Image *cache)
|
||||||
{
|
{
|
||||||
|
@ -646,24 +659,25 @@ evas_cache_image_shutdown(Evas_Cache_Image *cache)
|
||||||
|
|
||||||
#ifdef BUILD_ASYNC_PRELOAD
|
#ifdef BUILD_ASYNC_PRELOAD
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_lock(&mutex);
|
||||||
if (running)
|
|
||||||
|
Eina_Inlist *l, *l_next;
|
||||||
|
for (l = preload; l != NULL; l = l_next)
|
||||||
{
|
{
|
||||||
Eina_Inlist *l, *l_next;
|
Evas_Cache_Preload *tmp = (Evas_Cache_Preload *)l;
|
||||||
for (l = preload; l != NULL; l = l_next)
|
Image_Entry *ie = tmp->ie;
|
||||||
{
|
|
||||||
Evas_Cache_Preload *tmp = (Evas_Cache_Preload *)l;
|
|
||||||
Image_Entry *ie = tmp->ie;
|
|
||||||
|
|
||||||
l_next = l->next;
|
l_next = l->next;
|
||||||
|
|
||||||
if (ie->cache != cache)
|
if (ie->cache != cache)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
preload = eina_inlist_remove(preload, l);
|
preload = eina_inlist_remove(preload, l);
|
||||||
_evas_cache_image_entry_clear_preloaders(ie);
|
_evas_cache_image_entry_clear_preloaders(ie);
|
||||||
free(l);
|
free(l);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current && current->cache == cache)
|
||||||
|
_evas_cache_image_entry_clear_preloaders(current);
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -881,7 +895,7 @@ evas_cache_pending_process(void)
|
||||||
Image_Entry *im;
|
Image_Entry *im;
|
||||||
|
|
||||||
#ifdef BUILD_ASYNC_PRELOAD
|
#ifdef BUILD_ASYNC_PRELOAD
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_lock(&mutex_pending);
|
||||||
EINA_LIST_FREE(pending, im)
|
EINA_LIST_FREE(pending, im)
|
||||||
{
|
{
|
||||||
Evas_Cache_Image *cache = im->cache;
|
Evas_Cache_Image *cache = im->cache;
|
||||||
|
@ -908,7 +922,7 @@ evas_cache_pending_process(void)
|
||||||
evas_cache_image_flush(cache);
|
evas_cache_image_flush(cache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex_pending);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,27 +937,24 @@ evas_cache_image_drop(Image_Entry *im)
|
||||||
im->references--;
|
im->references--;
|
||||||
cache = im->cache;
|
cache = im->cache;
|
||||||
|
|
||||||
if (im->references == 0)
|
if (im->references == 0 && !im->flags.pending)
|
||||||
{
|
{
|
||||||
#ifdef BUILD_ASYNC_PRELOAD
|
#ifdef BUILD_ASYNC_PRELOAD
|
||||||
_evas_cache_image_entry_preload_remove(im, NULL);
|
|
||||||
/*
|
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_lock(&mutex);
|
||||||
if (im->flags.preload)
|
if (im->flags.preload || im->flags.in_pipe)
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
_evas_cache_image_entry_preload_remove(im, NULL);
|
_evas_cache_image_entry_preload_remove(im, NULL);
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_lock(&mutex_pending);
|
||||||
if (!im->flags.pending)
|
if (!im->flags.pending)
|
||||||
{
|
{
|
||||||
im->flags.pending = 1;
|
im->flags.pending = 1;
|
||||||
pending = eina_list_append(pending, im);
|
pending = eina_list_append(pending, im);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex_pending);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
*/
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (im->flags.dirty)
|
if (im->flags.dirty)
|
||||||
|
@ -1233,7 +1244,10 @@ evas_cache_image_load_data(Image_Entry *im)
|
||||||
assert(im->cache);
|
assert(im->cache);
|
||||||
cache = im->cache;
|
cache = im->cache;
|
||||||
|
|
||||||
if (im->flags.loaded) return;
|
if (im->flags.loaded)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
#ifdef BUILD_ASYNC_PRELOAD
|
#ifdef BUILD_ASYNC_PRELOAD
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_lock(&mutex);
|
||||||
preload = im->flags.preload;
|
preload = im->flags.preload;
|
||||||
|
@ -1285,21 +1299,18 @@ evas_cache_image_preload_data(Image_Entry *im, const void *target)
|
||||||
|
|
||||||
if (im->flags.loaded)
|
if (im->flags.loaded)
|
||||||
{
|
{
|
||||||
evas_async_events_put(target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL,
|
evas_object_event_callback_call((Evas_Object*) target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL);
|
||||||
(void (*)(void*, Evas_Callback_Type, void*))evas_object_event_callback_call);
|
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache = im->cache;
|
cache = im->cache;
|
||||||
|
|
||||||
if (!_evas_cache_image_entry_preload_add(im, target))
|
if (!_evas_cache_image_entry_preload_add(im, target))
|
||||||
evas_async_events_put(target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL,
|
evas_object_event_callback_call((Evas_Object*) target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL);
|
||||||
(void (*)(void*, Evas_Callback_Type, void*))evas_object_event_callback_call);
|
|
||||||
#else
|
#else
|
||||||
evas_cache_image_load_data(im);
|
evas_cache_image_load_data(im);
|
||||||
|
|
||||||
evas_async_events_put(target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL,
|
evas_object_event_callback_call((Evas_Object*) target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL);
|
||||||
(void (*)(void*, Evas_Callback_Type, void*))evas_object_event_callback_call);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1313,7 +1324,18 @@ evas_cache_image_preload_cancel(Image_Entry *im, const void *target)
|
||||||
assert(im->cache);
|
assert(im->cache);
|
||||||
cache = im->cache;
|
cache = im->cache;
|
||||||
|
|
||||||
|
if (target == NULL) return ;
|
||||||
|
|
||||||
_evas_cache_image_entry_preload_remove(im, target);
|
_evas_cache_image_entry_preload_remove(im, target);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&mutex_pending);
|
||||||
|
if (!im->flags.pending && im->flags.in_pipe)
|
||||||
|
{
|
||||||
|
im->flags.pending = 1;
|
||||||
|
pending = eina_list_append(pending, im);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&mutex_pending);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
(void) im;
|
(void) im;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -470,6 +470,7 @@ struct _Image_Entry_Flags
|
||||||
#ifdef BUILD_ASYNC_PRELOAD
|
#ifdef BUILD_ASYNC_PRELOAD
|
||||||
Eina_Bool preload : 1;
|
Eina_Bool preload : 1;
|
||||||
Eina_Bool pending : 1;
|
Eina_Bool pending : 1;
|
||||||
|
Eina_Bool in_pipe : 1;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue