and much pain and ganshing of teeth.. this took too long... no more hanging
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 22 Sep 2009 07:02:14 +0000 (07:02 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 22 Sep 2009 07:02:14 +0000 (07:02 +0000)
preload cancels. u can cancel a preload (explicitly or implicitly) with no
lock penalty. now i can get on with my other fun.

git-svn-id: http://svn.enlightenment.org/svn/e/trunk/evas@42616 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/cache/evas_cache.h
src/lib/cache/evas_cache_image.c
src/lib/canvas/evas_async_events.c
src/lib/canvas/evas_object_image.c
src/lib/include/evas_common.h

index 605d9cf..989d3e1 100644 (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);
index a80c413..1f11573 100644 (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
@@ -778,6 +874,43 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *
 }
 
 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)
 {
    Evas_Cache_Image    *cache;
@@ -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
index d0c95c4..f4fecb6 100644 (file)
@@ -143,6 +143,7 @@ evas_async_events_process(void)
           _fd_read = -1;
        }
 
+   evas_cache_pending_process();
    return count;
 #else
    return 0;
index f929a96..2b49140 100644 (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);
index 4e848a7..24f2cf7 100644 (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
 };