davemds pushed a commit to branch master.

http://git.enlightenment.org/enlightenment/modules/places.git/commit/?id=b682a5f9022614e935af8d3b6795cc01109f7eee

commit b682a5f9022614e935af8d3b6795cc01109f7eee
Author: Dave Andreoli <d...@gurumeditation.it>
Date:   Thu Nov 12 07:07:28 2020 +0100

    Move the statfvs() call in a separate thread
    
    statvfs can block, so run it in a thread to not stall the E mainloop
---
 src/e_mod_places.c | 136 +++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 111 insertions(+), 25 deletions(-)

diff --git a/src/e_mod_places.c b/src/e_mod_places.c
index 48c5b6c..75755da 100644
--- a/src/e_mod_places.c
+++ b/src/e_mod_places.c
@@ -17,8 +17,18 @@
 #endif
 
 
+/* Local Typedefs */
+typedef struct _FreespaceThreadData FreespaceThreadData;
+struct _FreespaceThreadData
+{
+   const char *id;
+   const char *mount_point;
+   unsigned long long size;
+   unsigned long long free_space;
+};
+
 /* Local Function Prototypes */
-static Eina_Bool _places_poller(void *data);
+static Eina_Bool _places_freespace_timer_cb(void *data);
 static const char *_places_human_size_get(unsigned long long size);
 static void _places_volume_object_update(Volume *vol, Evas_Object *obj);
 static void _places_run_fm_external(const char *fm, const char *directory);
@@ -30,9 +40,10 @@ void _places_eject_activated_cb(void *data, Evas_Object *o, 
const char *emission
 void _places_header_activated_cb(void *data, Evas_Object *o, const char 
*emission, const char *source);
 
 /* Local Variables */
-static Ecore_Timer *poller = NULL;
 static char theme_file[PATH_MAX];
-Eina_List *volumes = NULL;
+static Eina_List *volumes = NULL;
+static Ecore_Timer *freespace_timer = NULL;
+static Ecore_Thread *freespace_thread = NULL;
 
 
 /* Implementation */
@@ -55,13 +66,22 @@ places_init(void)
 
    snprintf(theme_file, PATH_MAX, "%s/e-module-places.edj",
             places_conf->module->dir);
-   poller = ecore_timer_add(3.0, _places_poller, NULL);
+   freespace_timer = ecore_timer_add(3.0, _places_freespace_timer_cb, NULL);
 }
 
 void
 places_shutdown(void)
 {
-   if (poller) ecore_timer_del(poller);
+   if (freespace_timer) 
+     {
+        ecore_timer_del(freespace_timer);
+        freespace_timer = NULL;
+     }
+   if (freespace_thread) 
+     {
+        ecore_thread_cancel(freespace_thread);
+        freespace_thread = NULL;
+     }
 
    while (volumes)
      places_volume_del((Volume*)volumes->data);
@@ -520,41 +540,107 @@ places_run_fm(const char *directory)
 
 
 /* Internals */
-static unsigned long long
-_places_free_space_get(const char *mount, Volume *vol)
+static void
+_places_freespace_thread_run(void *data, Ecore_Thread *thread)
 {
+   /* statvfs can block, so we run it in a thread to not stall the E mainloop 
*/
+   Eina_List *l;
+   FreespaceThreadData *td = NULL;
    struct statvfs s;
 
-   if (!mount) return 0;
-   if (statvfs(mount, &s) != 0)
-     return 0;
+   // printf("PLACES: THIS RUN IN THREAD %p\n", thread);
+
+   if (ecore_thread_check(thread) == EINA_TRUE)  // thread cancelled
+     return;
+
+   EINA_LIST_FOREACH(data, l, td)
+     {
+        if (td->mount_point && (statvfs(td->mount_point, &s) == 0)) 
+          {
+             td->size = (unsigned long long)s.f_blocks * (unsigned long 
long)s.f_frsize;
+             td->free_space = (unsigned long long)s.f_bavail * (unsigned long 
long)s.f_frsize;
+          }
+        if (ecore_thread_check(thread) == EINA_TRUE)
+          return;
+     }
+}
+
+static void
+_places_freespace_thread_done(void *data, Ecore_Thread *thread)
+{
+   FreespaceThreadData *td = NULL;
+   Volume *vol;
+
+   EINA_LIST_FREE(data, td)
+     {
+        vol = places_volume_by_id_get(td->id);
+        if (vol) 
+          {
+             // redraw only if size or free_space has changed more than 1Mb
+             if ((abs(td->free_space - vol->free_space) > 1024 * 1024) ||
+                 (abs(td->size - vol->size) > 1024 * 1024))
+               {
+                  vol->size = td->size;
+                  vol->free_space = td->free_space;
+                  places_volume_update(vol);
+               }
+          }
+        eina_stringshare_del(td->id);
+        eina_stringshare_del(td->mount_point);
+        E_FREE(td);
+     }
+
+   // printf("PLACES:    THREAD DONE %p\n", thread);
+   freespace_thread = NULL;
+}
 
-   if ((vol->size == 0) && (s.f_blocks))
-     vol->size = (unsigned long long)s.f_blocks * (unsigned long 
long)s.f_frsize;
+static void
+_places_freespace_thread_cancel(void *data, Ecore_Thread *thread)
+{
+   FreespaceThreadData *td = NULL;
 
-   return (unsigned long long)s.f_bavail * (unsigned long long)s.f_frsize;
+   EINA_LIST_FREE(data, td)
+     {
+        eina_stringshare_del(td->id);
+        eina_stringshare_del(td->mount_point);
+        E_FREE(td);
+     }
+   freespace_thread = NULL;
 }
 
 static Eina_Bool
-_places_poller(void *data)
+_places_freespace_timer_cb(void *data EINA_UNUSED)
 {
    Volume *vol;
-   Eina_List *l;
-   long long new;
+   Eina_List *l, *tdl = NULL;
+   FreespaceThreadData *td = NULL;
+
+   if (freespace_thread) 
+     {
+        // printf("PLACES: *** SOMETHING WRONG *** thread:%p still 
running...\n", freespace_thread);
+        return ECORE_CALLBACK_RENEW;
+     }
 
    EINA_LIST_FOREACH(volumes, l, vol)
-     if (vol->valid && vol->mounted)
      {
-        new = _places_free_space_get(vol->mount_point, vol);
-        // redraw only if the size has changed more that 1Mb
-        if (abs(new - vol->free_space) > 1024 * 1024)
+        if (vol->valid && vol->mounted)
           {
-             vol->free_space = new;
-             places_volume_update(vol);
+             td = E_NEW(FreespaceThreadData, 1);
+             if (!td) return ECORE_CALLBACK_RENEW;
+         
+             td->id = eina_stringshare_add(vol->id);
+             td->mount_point = eina_stringshare_add(vol->mount_point);
+             tdl = eina_list_append(tdl, td);
           }
-    }
-   
-   return EINA_TRUE;
+     }
+
+   if (tdl) 
+     freespace_thread = ecore_thread_run(_places_freespace_thread_run,
+                                         _places_freespace_thread_done,
+                                         _places_freespace_thread_cancel,
+                                         tdl);
+
+   return ECORE_CALLBACK_RENEW;
 }
 
 static const char *

-- 


Reply via email to