and much pain and ganshing of teeth.. this took too long... no more hanging

preload cancels. u can cancel a preload (explicitly or implicitly) with no
lock penalty. now i can get on with my other fun.



SVN revision: 42616
This commit is contained in:
Carsten Haitzler 2009-09-22 07:02:14 +00:00
parent 05126826a3
commit 85c9ee14e1
5 changed files with 175 additions and 99 deletions

View File

@ -111,6 +111,7 @@ extern "C" {
EAPI Evas_Cache_Image* evas_cache_image_init(const Evas_Cache_Image_Func *cb);
EAPI void evas_cache_image_shutdown(Evas_Cache_Image *cache);
EAPI Image_Entry* evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *key, RGBA_Image_Loadopts *lo, int *error);
EAPI void evas_cache_pending_process(void);
EAPI void evas_cache_image_drop(Image_Entry *im);
EAPI void evas_cache_image_data_not_needed(Image_Entry *im);
EAPI int evas_cache_image_flush(Evas_Cache_Image *cache);

View File

@ -36,6 +36,7 @@ struct _Evas_Cache_Preload
static Eina_Inlist *preload = NULL;
static Image_Entry *current = NULL;
static Eina_List *pending = NULL;
static pthread_cond_t cond_done = PTHREAD_COND_INITIALIZER;
static pthread_cond_t cond_new = PTHREAD_COND_INITIALIZER;
@ -80,6 +81,16 @@ _evas_cache_image_make_activ(Evas_Cache_Image *cache,
Image_Entry *im,
const char *key)
{
#ifdef BUILD_ASYNC_PRELOAD
pthread_mutex_lock(&mutex);
if (im->flags.pending)
{
im->flags.pending = 0;
pending = eina_list_remove(pending, im);
}
pthread_mutex_unlock(&mutex);
#endif
im->cache_key = key;
if (key != NULL)
{
@ -361,6 +372,11 @@ _evas_cache_image_entry_preload_add(Image_Entry *ie,
preload = eina_inlist_append(preload, EINA_INLIST_GET(tmp));
ie->flags.preload = 1;
if (ie->flags.pending)
{
ie->flags.pending = 0;
pending = eina_list_remove(pending, ie);
}
if (!running)
{
@ -395,13 +411,13 @@ _evas_cache_image_entry_preload_remove(Image_Entry *ie, const void *target)
if (running)
{
pthread_mutex_lock(&mutex);
if (ie->flags.preload)
{
if (current == ie)
{
/* Wait until ie is processed. */
pthread_cond_wait(&cond_done, &mutex);
// dont wait. simply handle "ie->flags.preload" nicely
// /* Wait until ie is processed. */
// pthread_cond_wait(&cond_done, &mutex);
}
else
{
@ -450,12 +466,92 @@ _evas_cache_image_entry_preload_remove(Image_Entry *ie, const void *target)
ret = 1;
}
}
pthread_mutex_unlock(&mutex);
}
return ret;
}
static void*
_evas_cache_background_load(void *data)
{
(void) data;
restart:
while (preload)
{
pthread_mutex_lock(&mutex);
if (preload)
{
Evas_Cache_Preload *tmp = (Evas_Cache_Preload*) preload;
current = tmp->ie;
preload = eina_inlist_remove(preload, preload);
free(tmp);
}
pthread_mutex_unlock(&mutex);
if (current)
{
Evas_Cache_Image *cache;
int error;
int pchannel;
LKL(current->lock);
pchannel = current->channel;
current->channel++;
cache = current->cache;
if (!current->flags.loaded)
{
error = cache->func.load(current);
if (cache->func.debug)
cache->func.debug("load", current);
if (error)
{
_evas_cache_image_entry_surface_alloc
(cache, current, current->w, current->h);
current->flags.loaded = 0;
}
else
current->flags.loaded = 1;
}
pthread_mutex_lock(&mutex);
current->flags.preload = 0;
current->channel = pchannel;
LKU(current->lock);
pthread_mutex_unlock(&mutex);
_evas_cache_image_async_call(current);
pthread_mutex_lock(&mutex);
current = NULL;
pthread_mutex_unlock(&mutex);
}
pthread_cond_signal(&cond_done);
}
pthread_mutex_lock(&mutex);
if (preload)
{
pthread_mutex_unlock(&mutex);
goto restart;
}
running = EINA_FALSE;
pthread_mutex_unlock(&mutex);
pthread_mutex_lock(&mutex_new);
pthread_cond_wait(&cond_new, &mutex_new);
pthread_mutex_unlock(&mutex_new);
goto restart;
return NULL;
}
#endif
EAPI int
@ -777,6 +873,43 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *
return NULL;
}
EAPI void
evas_cache_pending_process(void)
{
Image_Entry *im;
#ifdef BUILD_ASYNC_PRELOAD
pthread_mutex_lock(&mutex);
EINA_LIST_FREE(pending, im)
{
Evas_Cache_Image *cache = im->cache;
if (!im->flags.pending) continue;
im->flags.pending = 0;
if (im->flags.preload) continue;
if (im->flags.activ)
{
if (im->flags.dirty)
{
_evas_cache_image_entry_delete(cache, im);
}
else
{
_evas_cache_image_remove_activ(cache, im);
_evas_cache_image_make_inactiv(cache, im, im->cache_key);
evas_cache_image_flush(cache);
}
}
else if (im->flags.cached)
{
evas_cache_image_flush(cache);
}
}
pthread_mutex_unlock(&mutex);
#endif
}
EAPI void
evas_cache_image_drop(Image_Entry *im)
{
@ -791,15 +924,29 @@ evas_cache_image_drop(Image_Entry *im)
if (im->references == 0)
{
#ifdef BUILD_ASYNC_PRELOAD
_evas_cache_image_entry_preload_remove(im, NULL);
pthread_mutex_lock(&mutex);
if (im->flags.preload)
{
pthread_mutex_unlock(&mutex);
_evas_cache_image_entry_preload_remove(im, NULL);
pthread_mutex_lock(&mutex);
if (!im->flags.pending)
{
im->flags.pending = 1;
pending = eina_list_append(pending, im);
}
pthread_mutex_unlock(&mutex);
return;
}
pthread_mutex_unlock(&mutex);
#endif
if (im->flags.dirty)
{
_evas_cache_image_entry_delete(cache, im);
return ;
return;
}
_evas_cache_image_remove_activ(cache, im);
_evas_cache_image_make_inactiv(cache, im, im->cache_key);
evas_cache_image_flush(cache);
@ -1075,31 +1222,38 @@ EAPI void
evas_cache_image_load_data(Image_Entry *im)
{
Evas_Cache_Image *cache;
int error;
int error, preload;
assert(im);
assert(im->cache);
cache = im->cache;
if (im->flags.loaded) return ;
if (im->flags.loaded) return;
#ifdef BUILD_ASYNC_PRELOAD
int preload = im->flags.preload;
pthread_mutex_lock(&mutex);
preload = im->flags.preload;
/* We check a first time, to prevent useless lock. */
_evas_cache_image_entry_preload_remove(im, NULL);
if (preload)
{
if (current == im)
{
/* Wait until ie is processed. */
pthread_cond_wait(&cond_done, &mutex);
}
}
pthread_mutex_unlock(&mutex);
// _evas_cache_image_entry_preload_remove(im, NULL);
if (im->flags.loaded) return ;
LKL(im->lock);
#endif
error = cache->func.load(im);
#ifdef BUILD_ASYNC_PRELOAD
LKU(im->lock);
#endif
if (cache->func.debug)
cache->func.debug("load", im);
#ifdef BUILD_ASYNC_PRELOAD
if (preload)
_evas_cache_image_async_call(im);
@ -1109,7 +1263,6 @@ evas_cache_image_load_data(Image_Entry *im)
{
_evas_cache_image_entry_surface_alloc(cache, im, im->w, im->h);
im->flags.loaded = 0;
return ;
}
@ -1262,85 +1415,3 @@ evas_cache_image_pixels(Image_Entry *im)
return cache->func.surface_pixels(im);
}
#ifdef BUILD_ASYNC_PRELOAD
static void*
_evas_cache_background_load(void *data)
{
(void) data;
restart:
while (preload)
{
pthread_mutex_lock(&mutex);
if (preload)
{
Evas_Cache_Preload *tmp = (Evas_Cache_Preload*) preload;
current = tmp->ie;
preload = eina_inlist_remove(preload, preload);
free(tmp);
}
pthread_mutex_unlock(&mutex);
if (current)
{
Evas_Cache_Image *cache;
int error;
int pchannel;
LKL(current->lock);
pchannel = current->channel;
current->channel++;
cache = current->cache;
if (!current->flags.loaded)
{
error = cache->func.load(current);
if (cache->func.debug)
cache->func.debug("load", current);
if (error)
{
_evas_cache_image_entry_surface_alloc(cache, current,
current->w, current->h);
current->flags.loaded = 0;
}
else
{
current->flags.loaded = 1;
}
}
current->flags.preload = 0;
current->channel = pchannel;
LKU(current->lock);
_evas_cache_image_async_call(current);
current = NULL;
}
pthread_cond_signal(&cond_done);
}
pthread_mutex_lock(&mutex);
if (preload)
{
pthread_mutex_unlock(&mutex);
goto restart;
}
running = EINA_FALSE;
pthread_mutex_unlock(&mutex);
pthread_mutex_lock(&mutex_new);
pthread_cond_wait(&cond_new, &mutex_new);
pthread_mutex_unlock(&mutex_new);
goto restart;
return NULL;
}
#endif

View File

@ -143,6 +143,7 @@ evas_async_events_process(void)
_fd_read = -1;
}
evas_cache_pending_process();
return count;
#else
return 0;

View File

@ -280,12 +280,14 @@ evas_object_image_file_set(Evas_Object *obj, const char *file, const char *key)
if ((o->cur.key) && (key) && (!strcmp(o->cur.key, key)))
return;
}
/*
* WTF? why cancel a null image preload? this is just silly (tm)
if (!o->engine_data)
obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
o->engine_data,
obj);
*/
if (o->cur.file) eina_stringshare_del(o->cur.file);
if (o->cur.key) eina_stringshare_del(o->cur.key);
if (file) o->cur.file = eina_stringshare_add(file);

View File

@ -488,6 +488,7 @@ struct _Image_Entry_Flags
Eina_Bool alpha_sparse : 1;
#ifdef BUILD_ASYNC_PRELOAD
Eina_Bool preload : 1;
Eina_Bool pending : 1;
#endif
};