eio: rework efl_io_manager to use efl_future.
authorCedric Bail <cedric@osg.samsung.com>
Mon, 1 Aug 2016 04:41:05 +0000 (21:41 -0700)
committerCedric BAIL <cedric@osg.samsung.com>
Thu, 8 Sep 2016 22:16:23 +0000 (15:16 -0700)
src/lib/eio/efl_io_manager.c
src/lib/eio/efl_io_manager.eo
src/lib/eo/eina_types.eot

index 81514f5..c3c0809 100644 (file)
 # 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"
index f41a176..05304c2 100644 (file)
@@ -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;
-  }
 }
index 4191626..c7b9c95 100644 (file)
@@ -22,7 +22,6 @@ struct @extern Eina.Matrix3 {
 }
 
 struct @extern Eina.Inarray;
-struct @extern Eina.Binbuf;
 
 type @extern Eina.Unicode: uint32;