diff --git a/src/lib/eio/efl_io_manager.c b/src/lib/eio/efl_io_manager.c index 59af2d223b..fb1ab21439 100644 --- a/src/lib/eio/efl_io_manager.c +++ b/src/lib/eio/efl_io_manager.c @@ -57,6 +57,24 @@ _efl_io_manager_future_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUS eio_file_cancel(data); } +static void +_future_file_done_cb(void *data, Eio_File *handler) +{ + Eina_Promise *p = data; + + eina_promise_resolve(p, eina_value_uint64_init(handler->length)); +} + +static void +_future_file_error_cb(void *data, + Eio_File *handler EINA_UNUSED, + int error) +{ + Eina_Promise *p = data; + + eina_promise_reject(p, error); +} + static void _no_future(void *data, const Efl_Event *ev EINA_UNUSED) { @@ -153,6 +171,31 @@ _cleanup_info_progress(void *data) eina_array_free(existing); } +static void +_future_string_cb(void *data EINA_UNUSED, Eio_File *handler, Eina_Array *gather) +{ + EflIoPath paths = ecore_thread_local_data_find(handler->thread, ".paths"); + void *paths_data = ecore_thread_local_data_find(handler->thread, ".paths_data"); + Eina_Accessor *access; + unsigned int count; + Eina_Stringshare *s; + + if (!paths) + { + eina_array_free(gather); + return ; + } + + access = eina_array_accessor_new(gather); + paths(paths_data, access); + + // Cleanup strings, accessor and array + EINA_ACCESSOR_FOREACH(access, count, s) + eina_stringshare_del(s); + eina_accessor_free(access); + eina_array_free(gather); +} + static void _file_string_cb(void *data, Eio_File *handler, Eina_Array *gather) { @@ -320,31 +363,36 @@ _efl_io_manager_stat_ls(Eo *obj, return NULL; } -static Efl_Future * +static Eina_Future * _efl_io_manager_ls(Eo *obj, Efl_Io_Manager_Data *pd EINA_UNUSED, - const char *path) + const char *path, + void *paths_data, EflIoPath paths, Eina_Free_Cb paths_free_cb) { - Efl_Promise *p; + Eina_Promise *p; + Eina_Future *future; Eio_File *h; - Eo *loop = efl_loop_get(obj); - p = efl_add(EFL_PROMISE_CLASS, loop); + p = eina_promise_new(efl_loop_future_scheduler_get(obj), + _efl_io_manager_future_cancel, NULL); if (!p) return NULL; + future = eina_future_new(p); h = _eio_file_ls(path, - _file_string_cb, - _file_done_cb, - _file_error_cb, + _future_string_cb, + _future_file_done_cb, + _future_file_error_cb, p); if (!h) goto end; - efl_event_callback_array_add(p, promise_progress_handling(), h); - return efl_promise_future_get(p); + ecore_thread_local_data_add(h->thread, ".paths", paths, NULL, EINA_TRUE); + ecore_thread_local_data_add(h->thread, ".paths_data", paths_data, paths_free_cb, EINA_TRUE); + eina_promise_data_set(p, h); + + return efl_future_Eina_FutureXXX_then(obj, future); end: - efl_del(p); - return NULL; + return future; } /* Stat function */ @@ -453,14 +501,6 @@ _efl_io_manager_xattr_ls(Eo *obj, return NULL; } -static void -_future_file_done_cb(void *data, Eio_File *handler) -{ - Eina_Promise *p = data; - - eina_promise_resolve(p, eina_value_uint64_init(handler->length)); -} - static void _future_file_done_data_cb(void *data, Eio_File *handler EINA_UNUSED, const char *attr_data, unsigned int size) { @@ -478,16 +518,6 @@ _future_file_done_data_cb(void *data, Eio_File *handler EINA_UNUSED, const char eina_promise_resolve(p, v); } -static void -_future_file_error_cb(void *data, - Eio_File *handler EINA_UNUSED, - int error) -{ - Eina_Promise *p = data; - - eina_promise_reject(p, error); -} - static Eina_Future * _efl_io_manager_xattr_set(Eo *obj, Efl_Io_Manager_Data *pd EINA_UNUSED, diff --git a/src/lib/eio/efl_io_manager.eo b/src/lib/eio/efl_io_manager.eo index 8ad5443f01..b8ed9002e2 100644 --- a/src/lib/eio/efl_io_manager.eo +++ b/src/lib/eio/efl_io_manager.eo @@ -7,17 +7,32 @@ struct Eio.Data size: uint; [[Size of private data]] } +function EflIoPath { + params { + @in paths: accessor; [[Accessor to an array of path.]] + } +}; + +function EflIoDirectInfo { + params { + @in entries: accessor; [[Accessor to an array of info.]] + } +}; + class Efl.Io.Manager (Efl.Loop_User) { [[Class representing an asynchronous file operation.]] methods { ls { - [[Lists entries in a given path.]] + [[Lists entries in a given path. + See \@ref eina_file_ls(). + ]] params { @in path: string; [[Path we want to list entries for]] + paths: EflIoPath; [[Callback called for each packet of files found]] } - return: future)>; [[List of entries in path]] + return: ptr(Eina.Future) @owned; [[Amount of files found during the listing of the directory]] } direct_ls { diff --git a/src/tests/eio/eio_test_manager.c b/src/tests/eio/eio_test_manager.c index 8224af207a..4fa1767ed2 100644 --- a/src/tests/eio/eio_test_manager.c +++ b/src/tests/eio/eio_test_manager.c @@ -18,6 +18,19 @@ static Eina_Bool direct = EINA_FALSE; #define DONE_CALLED 0xdeadbeef +static void +_access_cb(void *data, Eina_Accessor *access) +{ + uint64_t *number_of_listed_files = data; + Eina_Stringshare *s; + unsigned int count; + + EINA_ACCESSOR_FOREACH(access, count, s) + { + (*number_of_listed_files)++; + } +} + static void _progress_cb(void *data, const Efl_Event *ev) { @@ -28,6 +41,36 @@ _progress_cb(void *data, const Efl_Event *ev) (*number_of_listed_files) += eina_array_count(batch); } +static Eina_Value +_future_cb(void *data, + const Eina_Value file, + const Eina_Future *dead EINA_UNUSED) +{ + if (file.type == EINA_VALUE_TYPE_ERROR) + { + Eina_Error err; + + eina_value_get(&file, &err); + fprintf(stderr, "Something has gone wrong: %s\n", eina_error_msg_get(err)); + abort(); + } + if (file.type == EINA_VALUE_TYPE_UINT64) + { + uint64_t *number_of_listed_files = data; + uint64_t value; + + eina_value_get(&file, &value); + + fail_if((*number_of_listed_files) != test_count); + fail_if(value != test_count); + *number_of_listed_files = DONE_CALLED; + } + + ecore_main_loop_quit(); + + return file; +} + static void _done_cb(void *data, const Efl_Event *ev) { @@ -196,7 +239,7 @@ START_TEST(efl_io_manager_test_ls) Eina_Tmpstr *nested_dirname; Eina_Tmpstr *nested_filename; Efl_Io_Manager *job; - Efl_Future *f; + Eina_Future *f; uint64_t main_files = 0; int ret; @@ -217,9 +260,9 @@ START_TEST(efl_io_manager_test_ls) job = efl_add(EFL_IO_MANAGER_CLASS, ecore_main_loop_get()); fail_if(!job); - f = efl_io_manager_ls(job, test_dirname); + f = efl_io_manager_ls(job, test_dirname, &main_files, _access_cb, NULL); test_count = 6; - efl_future_then(f, &_done_cb, &_error_cb, &_progress_cb, &main_files); + eina_future_then(f, _future_cb, &main_files); ecore_main_loop_begin();