Move the statfvs() call in a separate thread
statvfs can block, so run it in a thread to not stall the E mainloop
This commit is contained in:
parent
b25c7c5529
commit
b682a5f902
|
@ -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 ((vol->size == 0) && (s.f_blocks))
|
||||
vol->size = (unsigned long long)s.f_blocks * (unsigned long long)s.f_frsize;
|
||||
if (ecore_thread_check(thread) == EINA_TRUE) // thread cancelled
|
||||
return;
|
||||
|
||||
return (unsigned long long)s.f_bavail * (unsigned long long)s.f_frsize;
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
_places_freespace_thread_cancel(void *data, Ecore_Thread *thread)
|
||||
{
|
||||
FreespaceThreadData *td = NULL;
|
||||
|
||||
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 *
|
||||
|
|
Loading…
Reference in New Issue