cedric pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=52c63190d5b9906698b5e1872ce6448185218d91
commit 52c63190d5b9906698b5e1872ce6448185218d91 Author: Cedric Bail <ced...@osg.samsung.com> Date: Sun Jul 31 21:41:05 2016 -0700 eio: rework efl_io_manager to use efl_future. --- src/lib/eio/efl_io_manager.c | 758 ++++++++++++++++++++---------------------- src/lib/eio/efl_io_manager.eo | 105 ++---- src/lib/eo/eina_types.eot | 1 - 3 files changed, 383 insertions(+), 481 deletions(-) diff --git a/src/lib/eio/efl_io_manager.c b/src/lib/eio/efl_io_manager.c index 81514f5..c3c0809 100644 --- a/src/lib/eio/efl_io_manager.c +++ b/src/lib/eio/efl_io_manager.c @@ -22,10 +22,12 @@ # include <config.h> #endif - #include <Eo.h> +#include <Ecore.h> #include "Eio.h" +#include "eio_private.h" + typedef struct _Efl_Io_Manager_Data Efl_Io_Manager_Data; struct _Efl_Io_Manager_Data @@ -50,389 +52,364 @@ struct _Job_Closure /* Helper functions */ -static Job_Closure * -_job_closure_create(Eo *obj, Efl_Io_Manager_Data *pdata, Eina_Promise_Owner *owner) +static void +_no_future(void *data, const Efl_Event *ev EINA_UNUSED) { - EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(pdata, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(owner, NULL); - - Job_Closure *closure = malloc(sizeof(Job_Closure)); - - if (!closure) - { - EINA_LOG_CRIT("Failed to allocate memory."); - return 0; - } - - closure->object = efl_ref(obj); - closure->pdata = pdata; - closure->promise = owner; - closure->file = NULL; // Will be set once the Eio operation is under way - closure->delete_me = EINA_FALSE; - closure->delayed_arg = NULL; - closure->direct_func = NULL; - - pdata->operations = eina_list_prepend(pdata->operations, closure); + Eio_File *h = data; - return closure; + eio_file_cancel(h); } static void -_job_closure_del(Job_Closure *closure) +_forced_shutdown(void *data, const Efl_Event *ev EINA_UNUSED) { - EINA_SAFETY_ON_NULL_RETURN(closure); - Efl_Io_Manager_Data *pdata = closure->pdata; - if (pdata) - pdata->operations = eina_list_remove(pdata->operations, closure); + Eio_File *h = data; - efl_unref(closure->object); - - if (closure->delayed_arg) - free(closure->delayed_arg); - - free(closure); + eio_file_cancel(h); + // FIXME: handle memory lock here ! + // Acceptable strategy will be to unlock all thread as + // if we were freeing some memory + // FIXME: Handle long to finish thread + ecore_thread_wait(h->thread, 1.0); } static void -_file_error_cb(void *data, Eio_File *handler EINA_UNUSED, int error) +_progress(void *data EINA_UNUSED, const Efl_Event *ev) { - Job_Closure *operation = data; - - EINA_SAFETY_ON_NULL_RETURN(operation); - EINA_SAFETY_ON_NULL_RETURN(operation->promise); - - eina_promise_owner_error_set(operation->promise, error); - - _job_closure_del(operation); + efl_key_data_set(ev->object, "_eio.progress", (void*) EINA_TRUE); } -/* Basic listing callbacks */ - -static Eina_Bool -_file_ls_filter_cb_helper(const Efl_Event_Description *event, void *data, const char *file) -{ - Job_Closure *operation = data; - - EINA_SAFETY_ON_NULL_RETURN_VAL(operation, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(operation->pdata, EINA_FALSE); +EFL_CALLBACKS_ARRAY_DEFINE(promise_progress_handling, + { EFL_PROMISE_EVENT_FUTURE_PROGRESS_SET, _progress }, + { EFL_PROMISE_EVENT_FUTURE_NONE, _no_future }, + { EFL_EVENT_DEL, _forced_shutdown }); - Eio_Filter_Name_Data* event_info = malloc(sizeof(Eio_Filter_Name_Data)); +EFL_CALLBACKS_ARRAY_DEFINE(promise_handling, + { EFL_PROMISE_EVENT_FUTURE_NONE, _no_future }, + { EFL_EVENT_DEL, _forced_shutdown }); - EINA_SAFETY_ON_NULL_RETURN_VAL(event_info, EINA_FALSE); - - event_info->file = file; - event_info->filter = EINA_FALSE; +static void +_file_done_data_cb(void *data, Eio_File *handler, const char *attr_data, unsigned int size) +{ + Efl_Promise *p = data; + Eina_Binbuf *buf; - efl_event_callback_legacy_call(operation->pdata->object, event, event_info); + efl_event_callback_array_del(p, promise_handling(), handler); - Eina_Bool filter = event_info->filter; + buf = eina_binbuf_new(); + eina_binbuf_append_length(buf, (const unsigned char*) attr_data, size); - free(event_info); + efl_promise_value_set(p, buf, EINA_FREE_CB(eina_binbuf_free)); - return filter; + efl_del(p); } -static Eina_Bool -_file_ls_filter_xattr_cb(void *data, Eio_File *handler EINA_UNUSED, const char *file) +static void +_file_error_cb(void *data, Eio_File *handler, int error) { - return _file_ls_filter_cb_helper(EFL_IO_MANAGER_EVENT_XATTR, data, file); -} + Efl_Promise *p = data; -static Eina_Bool -_file_ls_filter_named_cb(void *data, Eio_File *handler EINA_UNUSED, const char *file) -{ - return _file_ls_filter_cb_helper(EFL_IO_MANAGER_EVENT_FILTER_NAME, data, file); -} + efl_event_callback_array_del(p, promise_handling(), handler); -static void -_file_ls_main_cb(void *data, Eio_File *handler EINA_UNUSED, const char *file) -{ - Job_Closure *operation = data; - EINA_SAFETY_ON_NULL_RETURN(operation); - EINA_SAFETY_ON_NULL_RETURN(operation->promise); + efl_promise_failed(p, error); - eina_promise_owner_progress(operation->promise, (void*)file); + efl_del(p); } static void -_file_done_cb(void *data, Eio_File *handler EINA_UNUSED) +_file_done_cb(void *data, Eio_File *handler) { - Job_Closure *operation = data; - - EINA_SAFETY_ON_NULL_RETURN(operation); - EINA_SAFETY_ON_NULL_RETURN(operation->promise); + Efl_Promise *p = data; + uint64_t *v = calloc(1, sizeof (uint64_t)); - // Placeholder value. We just want the callback to be called. - eina_promise_owner_value_set(operation->promise, NULL, NULL); + efl_event_callback_array_del(p, promise_handling(), handler); - _job_closure_del(operation); -} + if (!v) + { + efl_promise_failed(p, ENOMEM); + goto end; + } -static void -_free_xattr_data(Eio_Xattr_Data *value) -{ - EINA_SAFETY_ON_NULL_RETURN(value); - if (value->data) - free((void*)value->data); + *v = handler->length; + efl_promise_value_set(p, v, free); - free(value); + end: + efl_del(p); } +/* Basic listing callbacks */ static void -_file_done_data_cb(void *data, Eio_File *handler EINA_UNUSED, const char *attr_data, unsigned int size) +_cleanup_string_progress(void *data) { - Job_Closure *operation = data; - Eio_Xattr_Data *ret_data = NULL; - - EINA_SAFETY_ON_NULL_RETURN(operation); - EINA_SAFETY_ON_NULL_RETURN(operation->promise); + Eina_Array *existing = data; + Eina_Stringshare *s; + Eina_Array_Iterator it; + unsigned int i; - ret_data = calloc(sizeof(Eio_Xattr_Data), 1); - ret_data->data = calloc(sizeof(char), size + 1); - strcpy((char*)ret_data->data, attr_data); - ret_data->size = size; - - eina_promise_owner_value_set(operation->promise, ret_data, (Eina_Promise_Free_Cb)&_free_xattr_data); - - _job_closure_del(operation); + EINA_ARRAY_ITER_NEXT(existing, i, s, it) + eina_stringshare_del(s); + eina_array_free(existing); } -/* Direct listing callbacks */ - -static Eina_Bool -_file_direct_ls_filter_cb(void *data, Eio_File *handle EINA_UNUSED, const Eina_File_Direct_Info *info) +static void +_cleanup_info_progress(void *data) { - Job_Closure *operation = data; - - EINA_SAFETY_ON_NULL_RETURN_VAL(operation, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(operation->pdata, EINA_FALSE); + Eina_Array *existing = data; + Eio_File_Direct_Info *d; // This is a trick because we use the head of the structure + Eina_Array_Iterator it; + unsigned int i; - Eio_Filter_Direct_Data event_info; - - event_info.info = info; - event_info.filter = EINA_FALSE; - - efl_event_callback_legacy_call(operation->pdata->object, EFL_IO_MANAGER_EVENT_FILTER_DIRECT, &event_info); - - Eina_Bool filter = event_info.filter; - - return filter; + EINA_ARRAY_ITER_NEXT(existing, i, d, it) + eio_direct_info_free(d); + eina_array_free(existing); } static void -_file_direct_ls_main_cb(void *data, Eio_File *handler EINA_UNUSED, const Eina_File_Direct_Info *info) +_file_string_cb(void *data, Eio_File *handler, Eina_Array *gather) { - Job_Closure *operation = data; - EINA_SAFETY_ON_NULL_RETURN(operation); - EINA_SAFETY_ON_NULL_RETURN(operation->promise); + Efl_Promise *p = data; + Eina_Array *existing = efl_key_data_get(p, "_eio.stored"); + void **tmp; - eina_promise_owner_progress(operation->promise, (void*)info); -} + // If a future is set, but without progress, we should assume + // that we should discard all future progress. [[FIXME]] + if (existing) + { + tmp = realloc(existing->data, sizeof (void*) * (existing->count + gather->count)); + if (!tmp) + { + eina_array_free(gather); + eina_array_free(existing); + efl_key_data_set(p, "_eio.stored", NULL); + handler->error = ENOMEM; + eio_file_cancel(handler); + return ; + } + + existing->data = tmp; + memcpy(existing->data + existing->count, gather->data, gather->count * sizeof (void*)); + existing->count += gather->count; + existing->total = existing->count; + eina_array_free(gather); + } + else + { + existing = gather; + } -static void -_ls_direct_notify_start(void* data, Eina_Promise_Owner *promise EINA_UNUSED) -{ - Job_Closure *operation_data = (Job_Closure*)data; - char* path = operation_data->delayed_arg; - - Eio_File *handle = operation_data->direct_func(path, - _file_direct_ls_filter_cb, - _file_direct_ls_main_cb, - _file_done_cb, - _file_error_cb, - operation_data); - operation_data->file = handle; -} + if (!efl_key_data_get(p, "_eio.progress")) + { + efl_key_data_set(p, "_eio.stored", existing); + return ; + } -static void -_free_notify_start_data(void *data) -{ - Job_Closure *operation_data = (Job_Closure*)data; - if (!operation_data->delayed_arg) - return; - free(operation_data->delayed_arg); - operation_data->delayed_arg = NULL; + efl_promise_progress_set(p, existing); + efl_key_data_set(p, "_eio.stored", NULL); + _cleanup_string_progress(existing); } +/* Direct listing callbacks */ static void -_ls_notify_start(void *data, Eina_Promise_Owner* promise EINA_UNUSED) +_file_info_cb(void *data, Eio_File *handler, Eina_Array *gather) { - Job_Closure *operation_data = (Job_Closure*)data; - char* path = operation_data->delayed_arg; - - Eio_File *handle = eio_file_ls(path, - _file_ls_filter_named_cb, - _file_ls_main_cb, - _file_done_cb, - _file_error_cb, - operation_data); - operation_data->file = handle; -} + Efl_Promise *p = data; + Eina_Array *existing = efl_key_data_get(p, "_eio.stored"); + void **tmp; -static void -_xattr_notify_start(void *data, Eina_Promise_Owner *promise EINA_UNUSED) -{ - Job_Closure *operation_data = (Job_Closure*)data; - char* path = operation_data->delayed_arg; - - Eio_File *handle = eio_file_xattr(path, - _file_ls_filter_xattr_cb, - _file_ls_main_cb, - _file_done_cb, - _file_error_cb, - operation_data); - operation_data->file = handle; + // If a future is set, but without progress, we should assume + // that we should discard all future progress. [[FIXME]] + if (existing) + { + tmp = realloc(existing->data, sizeof (void*) * (existing->count + gather->count)); + if (!tmp) + { + eina_array_free(gather); + eina_array_free(existing); + efl_key_data_set(p, "_eio.stored", NULL); + handler->error = ENOMEM; + eio_file_cancel(handler); + return ; + } + existing->data = tmp; + memcpy(existing->data + existing->count, gather->data, gather->count * sizeof (void*)); + existing->count += gather->count; + existing->total = existing->count; + eina_array_free(gather); + } + else + { + existing = gather; + } + if (!efl_key_data_get(p, "_eio.progress")) + { + efl_key_data_set(p, "_eio.stored", existing); + return ; + } + efl_promise_progress_set(p, existing); + efl_key_data_set(p, "_eio.stored", NULL); + _cleanup_info_progress(existing); } -static void -_job_direct_ls_helper(Efl_Io_Manager_Direct_Ls_Func ls_func, - Eo* obj, - Efl_Io_Manager_Data *pd, - const char *path, - Eina_Promise_Owner *promise) +/* Method implementations */ +static Efl_Future * +_efl_io_manager_direct_ls(Eo *obj, + Efl_Io_Manager_Data *pd EINA_UNUSED, + const char *path, + Eina_Bool recursive) { - Job_Closure *operation_data = _job_closure_create(obj, pd, promise); + Efl_Promise *p; + Eio_File *h; - if (!operation_data) + p = efl_add(EFL_PROMISE_CLASS, obj); + if (!p) return NULL; + + if (!recursive) { - EINA_LOG_CRIT("Failed to create eio job operation data."); - eina_promise_owner_error_set(promise, eina_error_get()); - eina_error_set(0); - return; + h = _eio_file_direct_ls(path, + _file_info_cb, + _file_done_cb, + _file_error_cb, + p); + } + else + { + h = _eio_dir_direct_ls(path, + _file_info_cb, + _file_done_cb, + _file_error_cb, + p); } - operation_data->delayed_arg = (char*)calloc(sizeof(char), strlen(path) + 1); - strcpy(operation_data->delayed_arg, path); + if (!h) goto end; - operation_data->direct_func = ls_func; + efl_event_callback_array_add(p, promise_progress_handling(), h); + return efl_promise_future_get(p); - eina_promise_owner_progress_notify(promise, - _ls_direct_notify_start, - operation_data, - _free_notify_start_data); + end: + efl_del(p); + return NULL; } -/* Method implementations */ - -static Eina_Promise* -_efl_io_manager_file_direct_ls(Eo *obj, - Efl_Io_Manager_Data *pd, - const char *path) +static Efl_Future * +_efl_io_manager_stat_ls(Eo *obj, + Efl_Io_Manager_Data *pd EINA_UNUSED, + const char *path, + Eina_Bool recursive) { - Eina_Promise_Owner* promise = eina_promise_add(); - _job_direct_ls_helper(&eio_file_direct_ls, obj, pd, path, promise); - return eina_promise_owner_promise_get(promise); -} + Efl_Promise *p; + Eio_File *h; -static Eina_Promise* -_efl_io_manager_file_stat_ls(Eo *obj, - Efl_Io_Manager_Data *pd, - const char *path) -{ - Eina_Promise_Owner* promise = eina_promise_add(); - _job_direct_ls_helper(&eio_file_stat_ls, obj, pd, path, promise); - return eina_promise_owner_promise_get(promise); -} + p = efl_add(EFL_PROMISE_CLASS, obj); + if (!p) return NULL; -static Eina_Promise* -_efl_io_manager_dir_stat_ls(Eo *obj, - Efl_Io_Manager_Data *pd, - const char *path) -{ - Eina_Promise_Owner* promise = eina_promise_add(); - _job_direct_ls_helper(&eio_dir_stat_ls, obj, pd, path, promise); - return eina_promise_owner_promise_get(promise); -} + if (!recursive) + { + h = _eio_file_stat_ls(path, + _file_info_cb, + _file_done_cb, + _file_error_cb, + p); + } + else + { + h = _eio_dir_stat_ls(path, + _file_info_cb, + _file_done_cb, + _file_error_cb, + p); + } -static Eina_Promise* -_efl_io_manager_dir_direct_ls(Eo *obj, - Efl_Io_Manager_Data *pd, - const char *path) -{ - Eina_Promise_Owner* promise = eina_promise_add(); - // Had to add the cast as dir_direct differs in the filter callback constness of one of - // its arguments. - _job_direct_ls_helper((Efl_Io_Manager_Direct_Ls_Func)&eio_dir_direct_ls, obj, pd, path, promise); - return eina_promise_owner_promise_get(promise); + if (!h) goto end; + + efl_event_callback_array_add(p, promise_progress_handling(), h); + return efl_promise_future_get(p); + + end: + efl_del(p); + return NULL; } -static Eina_Promise* -_efl_io_manager_file_ls(Eo *obj, - Efl_Io_Manager_Data *pd, - const char *path) +static Efl_Future * +_efl_io_manager_ls(Eo *obj, + Efl_Io_Manager_Data *pd EINA_UNUSED, + const char *path) { - Eina_Promise_Owner* promise = eina_promise_add(); - Job_Closure *operation_data = _job_closure_create(obj, pd, promise); + Efl_Promise *p; + Eio_File *h; - Eina_Promise* p = eina_promise_owner_promise_get(promise); - if (!operation_data) - { - EINA_LOG_CRIT("Failed to create eio job operation data."); - eina_promise_owner_error_set(promise, eina_error_get()); - eina_error_set(0); - return p; - } + p = efl_add(EFL_PROMISE_CLASS, obj); + if (!p) return NULL; - operation_data->delayed_arg = (char*)calloc(sizeof(char), strlen(path) + 1); - strcpy(operation_data->delayed_arg, path); + h = _eio_file_ls(path, + _file_string_cb, + _file_done_cb, + _file_error_cb, + p); + if (!h) goto end; - eina_promise_owner_progress_notify(promise, - _ls_notify_start, - operation_data, - _free_notify_start_data); - return p; + efl_event_callback_array_add(p, promise_progress_handling(), h); + return efl_promise_future_get(p); + + end: + efl_del(p); + return NULL; } /* Stat function */ - static void _file_stat_done_cb(void *data, Eio_File *handle EINA_UNUSED, const Eina_Stat *stat) { - Job_Closure *operation = data; + Efl_Promise *p = data; + Eina_Stat *c; - EINA_SAFETY_ON_NULL_RETURN(operation); - EINA_SAFETY_ON_NULL_RETURN(operation->promise); - Eina_Stat *my_stat = calloc(sizeof(Eina_Stat), 1); + c = calloc(1, sizeof (Eina_Stat)); + if (!c) + { + efl_promise_failed(p, ENOMEM); + goto end; + } - *my_stat = *stat; - eina_promise_owner_value_set(operation->promise, my_stat, free); + memcpy(c, stat, sizeof (Eina_Stat)); + efl_promise_value_set(p, c, free); - _job_closure_del(operation); + end: + efl_del(p); } -static Eina_Promise* -_efl_io_manager_file_direct_stat(Eo *obj, - Efl_Io_Manager_Data *pd, - const char *path) +static Efl_Future * +_efl_io_manager_stat(Eo *obj, + Efl_Io_Manager_Data *pd EINA_UNUSED, + const char *path) { - Eina_Promise_Owner* promise = eina_promise_add(); - Job_Closure *operation_data = _job_closure_create(obj, pd, promise); + Efl_Promise *p; + Eio_File *h; - Eina_Promise* p = eina_promise_owner_promise_get(promise); - if (!operation_data) - { - EINA_LOG_CRIT("Failed to create eio job operation data."); - eina_promise_owner_error_set(promise, eina_error_get()); - eina_error_set(0); - return p; - } + p = efl_add(EFL_PROMISE_CLASS, obj); + if (!p) return NULL; - Eio_File *handle = eio_file_direct_stat(path, - _file_stat_done_cb, - _file_error_cb, - operation_data); - operation_data->file = handle; - return p; + h = eio_file_direct_stat(path, + _file_stat_done_cb, + _file_error_cb, + p); + if (!h) goto end; + + efl_event_callback_array_add(p, promise_handling(), h); + return efl_promise_future_get(p); + + end: + efl_del(p); + return NULL; } /* eXtended attribute manipulation */ -static Eina_Promise* -_efl_io_manager_file_xattr_list_get(Eo *obj, - Efl_Io_Manager_Data *pd, - const char *path) +static Efl_Future * +_efl_io_manager_xattr_ls(Eo *obj, + Efl_Io_Manager_Data *pd, + const char *path) { + // FIXME +#if 0 Eina_Promise_Owner *promise = eina_promise_add(); Job_Closure *operation_data = _job_closure_create(obj, pd, promise); @@ -453,149 +430,128 @@ _efl_io_manager_file_xattr_list_get(Eo *obj, operation_data, _free_notify_start_data); return p; +#endif } -static Eina_Promise* -_efl_io_manager_file_xattr_set(Eo *obj, - Efl_Io_Manager_Data *pd, - const char *path, - const char *attribute, - const char *xattr_data, - unsigned int xattr_size, - Eina_Xattr_Flags flags) +static Efl_Future * +_efl_io_manager_xattr_set(Eo *obj, + Efl_Io_Manager_Data *pd EINA_UNUSED, + const char *path, + const char *attribute, + Eina_Binbuf *data, + Eina_Xattr_Flags flags) { - Eina_Promise_Owner* promise = eina_promise_add(); - Job_Closure *operation_data = _job_closure_create(obj, pd, promise); + Efl_Promise *p; + Eio_File *h; - Eina_Promise* p = eina_promise_owner_promise_get(promise); + p = efl_add(EFL_PROMISE_CLASS, obj); + if (!p) return NULL; - if (!operation_data) - { - EINA_LOG_CRIT("Failed to create eio job operation data."); - eina_promise_owner_error_set(promise, eina_error_get()); - eina_error_set(0); - return p; - } + h = eio_file_xattr_set(path, attribute, + (const char *) eina_binbuf_string_get(data), + eina_binbuf_length_get(data), + flags, + _file_done_cb, + _file_error_cb, + p); + if (!h) goto end; - Eio_File *handle = eio_file_xattr_set(path, - attribute, - xattr_data, - xattr_size, - flags, - _file_done_cb, - _file_error_cb, - operation_data); - operation_data->file = handle; - return p; + efl_event_callback_array_add(p, promise_handling(), h); + return efl_promise_future_get(p); + + end: + efl_del(p); + return NULL; } -static Eina_Promise* -_efl_io_manager_file_xattr_get(Eo *obj, - Efl_Io_Manager_Data *pd, - const char *path, - const char *attribute) +static Efl_Future * +_efl_io_manager_xattr_get(Eo *obj, + Efl_Io_Manager_Data *pd EINA_UNUSED, + const char *path, + const char *attribute) { - Eina_Promise_Owner* promise = eina_promise_add(); - Job_Closure *operation_data = _job_closure_create(obj, pd, promise); + Efl_Promise *p; + Eio_File *h; - Eina_Promise* p = eina_promise_owner_promise_get(promise); - if (!operation_data) - { - EINA_LOG_CRIT("Failed to create eio job operation data."); - eina_promise_owner_error_set(promise, eina_error_get()); - eina_error_set(0); - return p; - } + p = efl_add(EFL_PROMISE_CLASS, obj); + if (!p) return NULL; - Eio_File *handle = eio_file_xattr_get(path, - attribute, - _file_done_data_cb, - _file_error_cb, - operation_data); - operation_data->file = handle; - return p; -} + h = eio_file_xattr_get(path, attribute, + _file_done_data_cb, + _file_error_cb, + p); + if (!h) goto end; -static void -_file_open_open_cb(void *data, Eio_File *handler EINA_UNUSED, Eina_File *file) -{ - Job_Closure *operation = data; - EINA_SAFETY_ON_NULL_RETURN(operation); - EINA_SAFETY_ON_NULL_RETURN(operation->promise); - eina_promise_owner_value_set(operation->promise, file, (Eina_Promise_Free_Cb)&eina_file_close); + efl_event_callback_array_add(p, promise_handling(), h); + return efl_promise_future_get(p); - _job_closure_del(operation); + end: + efl_del(p); + return NULL; } -static Eina_Promise* -_efl_io_manager_file_open(Eo *obj, - Efl_Io_Manager_Data *pd, - const char *path, - Eina_Bool shared) +static void +_file_open_cb(void *data, Eio_File *handler, Eina_File *file) { - Eina_Promise_Owner* promise = eina_promise_add(); - Job_Closure *operation_data = _job_closure_create(obj, pd, promise); + Efl_Promise *p = data; - Eina_Promise* p = eina_promise_owner_promise_get(promise); - if (!operation_data) - { - EINA_LOG_CRIT("Failed to create eio job operation data."); - eina_promise_owner_error_set(promise, eina_error_get()); - eina_error_set(0); - return p; - } + efl_event_callback_array_del(p, promise_handling(), handler); - Eio_File *handle = eio_file_open(path, shared, _file_open_open_cb, _file_error_cb, operation_data); - operation_data->file = handle; - return p; -} + efl_promise_value_set(p, eina_file_dup(file), EINA_FREE_CB(eina_file_close)); + efl_del(p); +} -static void -_file_close_done_cb(void *data, Eio_File *handler EINA_UNUSED) +static Efl_Future * +_efl_io_manager_open(Eo *obj, + Efl_Io_Manager_Data *pd EINA_UNUSED, + const char *path, + Eina_Bool shared) { - EINA_SAFETY_ON_NULL_RETURN(data); - Job_Closure *operation = data; - eina_promise_owner_value_set(operation->promise, NULL, NULL); + Efl_Promise *p; + Eio_File *h; - _job_closure_del(operation); -} + p = efl_add(EFL_PROMISE_CLASS, obj); + if (!p) return NULL; -static void -_efl_io_manager_file_close(Eo *obj, - Efl_Io_Manager_Data *pd, - Eina_File *file, - Eina_Promise_Owner *promise) -{ - Job_Closure *operation_data = _job_closure_create(obj, pd, promise); + h = eio_file_open(path, shared, + _file_open_cb, + _file_error_cb, + p); - if (!operation_data) - { - EINA_LOG_CRIT("Failed to create eio job operation data."); - return; - } + if (!h) goto end; + + efl_event_callback_array_add(p, promise_handling(), h); + return efl_promise_future_get(p); - Eio_File *handle = eio_file_close(file, _file_close_done_cb, _file_error_cb, operation_data); - operation_data->file = handle; + end: + efl_del(p); + return NULL; } -static Efl_Object* -_efl_io_manager_efl_object_constructor(Eo *obj, Efl_Io_Manager_Data *pd EINA_UNUSED) +static Efl_Future * +_efl_io_manager_close(Eo *obj, + Efl_Io_Manager_Data *pd EINA_UNUSED, + Eina_File *file) { - obj = efl_constructor(efl_super(obj, EFL_IO_MANAGER_CLASS)); + Efl_Promise *p; + Eio_File *h; - pd->object = obj; - pd->operations = NULL; + p = efl_add(EFL_PROMISE_CLASS, obj); + if (!p) return NULL; - return obj; -} + h = eio_file_close(file, + _file_done_cb, + _file_error_cb, + p); + if (!h) goto end; -static void -_efl_io_manager_efl_object_destructor(Eo *obj, Efl_Io_Manager_Data *pd EINA_UNUSED) -{ - efl_destructor(efl_super(obj, EFL_IO_MANAGER_CLASS)); + efl_event_callback_array_add(p, promise_handling(), h); + return efl_promise_future_get(p); - // FIXME: cancel all pending promise + end: + efl_del(p); + return NULL; } #include "efl_io_manager.eo.c" diff --git a/src/lib/eio/efl_io_manager.eo b/src/lib/eio/efl_io_manager.eo index f41a176..05304c2 100644 --- a/src/lib/eio/efl_io_manager.eo +++ b/src/lib/eio/efl_io_manager.eo @@ -7,118 +7,75 @@ struct Eio.Data size: uint; } -// FIXME: all events should be Eo objects not data if we want to modify them - -struct Eio.Filter.Direct.Data -{ - info: const(Eina.File.Direct.Info)*; - filter: bool; -} - -struct Eio.Filter.Name.Data -{ - file: string; - filter: bool; -} - -struct Eio.Xattr.Data -{ - data: string; - size: uint; -} - -// FIXME: We should send list of stuff in progress not single item, callback cost is to high - -class Efl.Io.Manager (Efl.Object) +class Efl.Io.Manager (Efl.Loop_User) { [[Class representing an asynchronous file operation.]] methods { - - file_ls { + ls { [[Lists entries in a given path.]] params { @in path: string; } - return: promise<int, string>; + return: future<uint64, const(array<string>)>; } - file_direct_ls { + direct_ls { [[Lists entries in a given path with more information.]] params { @in path: string; + @in recursive: bool; } - return: promise<int, const(Eina_File_Direct_Info)*>; + return: future<uint64, const(array<Eina_File_Direct_Info>)>; } - file_stat_ls { + stat_ls { [[Lists entries in a given path with stat information.]] params { @in path: string; + @in recursive: bool; } - return: promise<int, const(Eina_File_Direct_Info)*>; + return: future<uint64, const(array<Eina_File_Direct_Info>)>; } - dir_stat_ls { - [[Recursively list the directory content and its sub content.]] - params { - @in path: string; - } - return: promise<int, const(Eina_File_Direct_Info)*>; - } - - dir_direct_ls { - [[Recursively list the directory content and its sub content.]] + // Extended attributes + xattr_ls { + [[Lists all extended attributes asynchronously.]] params { - @in path: string; + @in path: string; } - return: promise<int, const(Eina_File_Direct_Info)*>; + return: future<uint64, const(array<string>)>; } - file_direct_stat { + stat { [[Get stat info on a given file/directory.]] params { @in path: string; } - return: promise<Eina_Stat>; - } - - // Extended attributes - @property file_xattr_list { - [[Lists all extended attributes asynchronously.]] - keys { - path: string; - } - get { - return: promise<int, string>; - } + return: future<Eina_Stat>; } - @property file_xattr { + // FIXME: Add helper for Eina.Value to Xattr + @property xattr { [[Retrieves or sets information of a given extended attribute.]] set { values { - attribute: string; - xattr_data: string; - xattr_size: uint; + data: Eina.Binbuf *; flags: Eina.Xattr.Flags; } - return: promise<int>; + return: future<uint64>; } get { - keys { - path: string; - attribute: string; - } - return: promise<Eio.Xattr.Data>; + return: future<Eina.Binbuf>; } keys { path: string; + attribute: string; } } // helper api - file_open { + open { [[Opens a file. The fulfilled value in the promise will be the Eina.File*.]] @@ -126,25 +83,15 @@ class Efl.Io.Manager (Efl.Object) @in path: string; @in shared: bool; } - return: promise<Eina.File*>; + return: future<Eina.File>; } - file_close { + close { [[Closes an open Eina.File.]] params { @in file: Eina.File*; // Here we're just interested whether the promise was fullfilled or not. No value needed. - @inout promise: promise<int>; } + return: future<int>; } } - events { - filter,name: Eio.Filter.Name.Data; - filter,direct: Eio.Filter.Direct.Data; - xattr: Eio.Filter.Name.Data; - } - - implements { - Efl.Object.constructor; - Efl.Object.destructor; - } } diff --git a/src/lib/eo/eina_types.eot b/src/lib/eo/eina_types.eot index 4191626..c7b9c95 100644 --- a/src/lib/eo/eina_types.eot +++ b/src/lib/eo/eina_types.eot @@ -22,7 +22,6 @@ struct @extern Eina.Matrix3 { } struct @extern Eina.Inarray; -struct @extern Eina.Binbuf; type @extern Eina.Unicode: uint32; --