ecore_con: migrate efl_net_ip_address_resolve to use Eina_Future.
authorCedric BAIL <cedric@osg.samsung.com>
Fri, 27 Apr 2018 23:20:47 +0000 (16:20 -0700)
committerWonki Kim <wonki_.kim@samsung.com>
Thu, 31 May 2018 07:01:00 +0000 (16:01 +0900)
src/lib/ecore_con/efl_net_ip_address.c
src/lib/ecore_con/efl_net_ip_address.eo
src/tests/ecore_con/ecore_con_test_efl_net_ip_address.c

index 802cd20..097d233 100644 (file)
@@ -26,6 +26,17 @@ typedef struct _Efl_Net_Ip_Address_Data {
    Eina_Slice addr_slice;
 } Efl_Net_Ip_Address_Data;
 
+typedef struct _Efl_Net_Ip_Address_Resolve_Value
+{
+   Eina_Stringshare *request_address; /**< The 'address' argument given to
+                                 * Efl.Net.Ip_Address.resolve */
+   Eina_Stringshare *canonical_name; /**< The canonical name, if it was requested in
+                                * flags */
+   const Eina_Value_Array results;  /**< The resolved objects. Do not modify this array but
+                                     * you can keep reference to elements using efl_ref()
+                                     * and efl_unref() */
+} Efl_Net_Ip_Address_Resolve_Value;
+
 #define MY_CLASS EFL_NET_IP_ADDRESS_CLASS
 
 EOLIAN static Eo *
@@ -362,80 +373,74 @@ _efl_net_ip_address_parse(Eo *cls, void *pd EINA_UNUSED, const char *numeric_add
 }
 
 typedef struct _Efl_Net_Ip_Address_Resolve_Context {
-   Efl_Net_Ip_Address_Resolve_Results *result;
+   Eina_Stringshare *request_address;
    Ecore_Thread *thread;
-   Efl_Promise *promise;
+   Eina_Promise *promise;
 } Efl_Net_Ip_Address_Resolve_Context;
 
-static void
-_efl_net_ip_address_resolve_results_free(void *data)
+static Eina_Value_Struct_Desc *
+_efl_net_ip_address_resolve_value_desc_get(void)
 {
-   Efl_Net_Ip_Address_Resolve_Results *r = data;
-
-   if (r->results)
-     {
-        Eina_Array_Iterator it;
-        unsigned int i;
-        Efl_Net_Ip_Address *o;
-
-        EINA_ARRAY_ITER_NEXT(r->results, i, o, it)
-          efl_unref(o);
-
-        eina_array_free(r->results);
-        r->results = NULL;
-     }
+   static Eina_Value_Struct_Member struct_members[] = {
+     // no eina_value_type as they are not constant initializers, see below.
+     EINA_VALUE_STRUCT_MEMBER(NULL, Efl_Net_Ip_Address_Resolve_Value, canonical_name),
+     EINA_VALUE_STRUCT_MEMBER(NULL, Efl_Net_Ip_Address_Resolve_Value, request_address),
+     EINA_VALUE_STRUCT_MEMBER(NULL, Efl_Net_Ip_Address_Resolve_Value, results)
+   };
+   static Eina_Value_Struct_Desc struct_desc = {
+      EINA_VALUE_STRUCT_DESC_VERSION,
+      NULL,
+      struct_members,
+      EINA_C_ARRAY_LENGTH(struct_members),
+      sizeof (Efl_Net_Ip_Address_Resolve_Value)
+   };
+   struct_members[0].type = EINA_VALUE_TYPE_STRINGSHARE;
+   struct_members[1].type = EINA_VALUE_TYPE_STRINGSHARE;
+   struct_members[2].type = EINA_VALUE_TYPE_ARRAY;
+   struct_desc.ops = EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH;
 
-   eina_stringshare_replace(&r->canonical_name, NULL);
-   eina_stringshare_replace(&r->request_address, NULL);
-   free(r);
+   return &struct_desc;
 }
 
 static void
-_efl_net_ip_address_resolve_del(void *data, const Efl_Event *event EINA_UNUSED)
+_efl_net_ip_address_resolve_del(void *data,
+                                const Eina_Promise *dead_promise EINA_UNUSED)
 {
    Efl_Net_Ip_Address_Resolve_Context *ctx = data;
 
    ctx->promise = NULL;
 
+   eina_stringshare_replace(&ctx->request_address, NULL);
+
    if (ctx->thread)
      {
         ecore_thread_cancel(ctx->thread);
         ctx->thread = NULL;
      }
 
-   if (ctx->result)
-     {
-        _efl_net_ip_address_resolve_results_free(ctx->result);
-        ctx->result = NULL;
-     }
-
    free(ctx);
 }
 
 static inline int
-_efl_net_ip_address_find(const Eina_Array *array, const struct sockaddr *addr)
+_efl_net_ip_address_find(const Eina_Value *array, const struct sockaddr *addr)
 {
-   Eina_Array_Iterator it;
-   unsigned int i;
    const Efl_Net_Ip_Address *o;
+   unsigned int i, len;
 
-   if (addr->sa_family == AF_INET6)
+   EINA_VALUE_ARRAY_FOREACH(array, len, i, o)
      {
-        EINA_ARRAY_ITER_NEXT(array, i, o, it)
+        const struct sockaddr *other = efl_net_ip_address_sockaddr_get(o);
+
+        if (addr->sa_family == AF_INET6)
           {
-             const struct sockaddr *other = efl_net_ip_address_sockaddr_get(o);
              if (other->sa_family == AF_INET6)
                {
                   if (memcmp(other,  addr, sizeof(struct sockaddr_in6)) == 0)
                     return (int)i;
                }
           }
-     }
-   else
-     {
-        EINA_ARRAY_ITER_NEXT(array, i, o, it)
+        else
           {
-             const struct sockaddr *other = efl_net_ip_address_sockaddr_get(o);
              if (other->sa_family == AF_INET)
                {
                   if (memcmp(other,  addr, sizeof(struct sockaddr_in)) == 0)
@@ -447,66 +452,89 @@ _efl_net_ip_address_find(const Eina_Array *array, const struct sockaddr *addr)
 }
 
 static void
-_efl_net_ip_address_resolve_done(void *data, const char *host, const char *port, const struct addrinfo *hints EINA_UNUSED, struct addrinfo *result, int gai_error)
+_efl_net_ip_address_resolve_done(void *data,
+                                 const char *host, const char *port,
+                                 const struct addrinfo *hints EINA_UNUSED,
+                                 struct addrinfo *result,
+                                 int gai_error)
 {
    Efl_Net_Ip_Address_Resolve_Context *ctx = data;
-   Efl_Net_Ip_Address_Resolve_Results *r;
+   Eina_Value_Array desc = { 0 };
+   Eina_Value s = EINA_VALUE_EMPTY;
+   Eina_Value r = EINA_VALUE_EMPTY;
+   Eina_Error err = EFL_NET_ERROR_COULDNT_RESOLVE_HOST;
    const struct addrinfo *a;
 
    DBG("done resolving '%s' (host='%s', port='%s'): %s",
-       ctx->result->request_address, host, port,
+       ctx->request_address, host, port,
        gai_error ? gai_strerror(gai_error) : "success");
 
    ctx->thread = NULL;
 
    if (gai_error)
      {
-        Eina_Error err = EFL_NET_ERROR_COULDNT_RESOLVE_HOST;
-
         if (gai_error == EAI_SYSTEM)
           err = errno;
 
-        efl_promise_failed_set(ctx->promise, err);
-        return;
+        goto on_error;
      }
 
-   ctx->result->results = eina_array_new(16);
-   if (!ctx->result->results)
-     {
-        efl_promise_failed_set(ctx->promise, ENOMEM);
-        return;
-     }
+   err = ENOMEM;
+   if (!eina_value_array_setup(&r, EINA_VALUE_TYPE_OBJECT, 1))
+     goto on_error;
+
+   if (!eina_value_struct_setup(&s, _efl_net_ip_address_resolve_value_desc_get()))
+     goto on_error;
 
-   r = ctx->result;
-   ctx->result = NULL; /* steal for efl_promise_value_set() */
+   eina_value_struct_set(&s, "request_address", ctx->request_address);
 
    for (a = result; a != NULL; a = a->ai_next)
      {
+        Eina_Stringshare *canonical_name = NULL;
         Eo *o;
 
-        if (EINA_UNLIKELY((r->canonical_name == NULL) &&
+        eina_value_struct_get(&s, "canonical_name", &canonical_name);
+        if (EINA_UNLIKELY((canonical_name == NULL) &&
                           (a->ai_canonname != NULL)))
-          r->canonical_name = eina_stringshare_add(a->ai_canonname);
+          {
+             canonical_name = eina_stringshare_add(a->ai_canonname);
+             eina_value_struct_set(&s, "canonical_name", canonical_name);
+             eina_stringshare_del(canonical_name);
+          }
 
         /* some addresses get duplicated with different options that we
          * do not care, so check for duplicates.
          */
-        if (EINA_UNLIKELY(_efl_net_ip_address_find(r->results, a->ai_addr) >= 0))
+        if (EINA_UNLIKELY(_efl_net_ip_address_find(&r, a->ai_addr) >= 0))
           continue;
 
         o = efl_net_ip_address_create_sockaddr(EFL_NET_IP_ADDRESS_CLASS, a->ai_addr);
-        if (o)
-          {
-             if (!eina_array_push(r->results, o))
-               efl_unref(o);
-          }
+        if (!o) continue ;
+
+        eina_value_array_append(&r, o);
+        efl_unref(o);
      }
    freeaddrinfo(result);
 
-   efl_promise_value_set(ctx->promise, r, _efl_net_ip_address_resolve_results_free);
+   if (!eina_value_pget(&r, &desc)) goto on_error;
+   if (!eina_value_struct_pset(&s, "results", &desc)) goto on_error;
+   eina_value_flush(&r);
+
+   eina_promise_resolve(ctx->promise, s);
+
+   eina_stringshare_replace(&ctx->request_address, NULL);
+   free(ctx);
+
+   return ;
+
+ on_error:
+   eina_promise_reject(ctx->promise, err);
+
+   eina_stringshare_replace(&ctx->request_address, NULL);
+   free(ctx);
 }
 
-EOLIAN static Efl_Future *
+EOLIAN static Eina_Future *
 _efl_net_ip_address_resolve(Eo *cls EINA_UNUSED, void *pd EINA_UNUSED, const char *address, int family, int flags)
 {
    Efl_Net_Ip_Address_Resolve_Context *ctx;
@@ -538,29 +566,23 @@ _efl_net_ip_address_resolve(Eo *cls EINA_UNUSED, void *pd EINA_UNUSED, const cha
    ctx = calloc(1, sizeof(Efl_Net_Ip_Address_Resolve_Context));
    EINA_SAFETY_ON_NULL_GOTO(ctx, error_ctx);
 
-   ctx->result = calloc(1, sizeof(Efl_Net_Ip_Address_Resolve_Results));
-   EINA_SAFETY_ON_NULL_GOTO(ctx->result, error_result);
-
-   ctx->result->request_address = eina_stringshare_add(address);
-   EINA_SAFETY_ON_NULL_GOTO(ctx->result->request_address, error_result_address);
+   ctx->request_address = eina_stringshare_add(address);
+   EINA_SAFETY_ON_NULL_GOTO(ctx->request_address, error_result_address);
 
    ctx->thread = efl_net_ip_resolve_async_new(host, port, &hints, _efl_net_ip_address_resolve_done, ctx);
    EINA_SAFETY_ON_NULL_GOTO(ctx->thread, error_thread);
 
-   ctx->promise = efl_add(EFL_PROMISE_CLASS, efl_main_loop_get(),
-                          efl_event_callback_add(efl_added, EFL_EVENT_DEL, _efl_net_ip_address_resolve_del, ctx));
+   ctx->promise = eina_promise_new(efl_loop_future_scheduler_get(efl_main_loop_get()), _efl_net_ip_address_resolve_del, ctx);
    EINA_SAFETY_ON_NULL_GOTO(ctx->promise, error_promise);
 
    free(str);
-   return efl_promise_future_get(ctx->promise);
+   return eina_future_new(ctx->promise);
 
  error_promise:
    ecore_thread_cancel(ctx->thread);
  error_thread:
-   eina_stringshare_del(ctx->result->request_address);
+   eina_stringshare_del(ctx->request_address);
  error_result_address:
-   free(ctx->result);
- error_result:
    free(ctx);
  error_ctx:
    free(str);
index e715a0c..dfb9953 100644 (file)
@@ -112,7 +112,7 @@ class Efl.Net.Ip_Address (Efl.Object) {
                 family: int @optional; [[Preferred family. AF_UNSPEC or 0 for both, otherwise one of AF_INET or AF_INET6]]
                 flags: int @optional; [[Flags to use with getaddrinfo(). If 0, default flags are used (AI_V4MAPPED | AI_ADDRCONFIG, if these exist in your system).]]
             }
-            return: future<const(Efl.Net.Ip_Address.Resolve_Results)>; [[The resolve results. It contains a list of Efl.Net.Ip_Address, they will be automatically deleted unless you keep a reference to it.]]
+            return: ptr(Eina.Future); [[The resolve results. It contains a list of Efl.Net.Ip_Address, they will be automatically deleted unless you keep a reference to it.]]
         }
 
         @property string {
index a32f6ee..b44bd0b 100644 (file)
@@ -128,51 +128,38 @@ _timeout(void *data,
 
 
 struct resolve_ctx {
-   Eina_Array *results;
+   Eina_Value *results;
    Eina_Stringshare *canonical_name;
    Eina_Stringshare *request_address;
-   Efl_Future *future;
+   Eina_Future *future;
    Eina_Error err;
 };
 
 static void
 _resolve_cleanup(struct resolve_ctx *ctx)
 {
-   Eina_Array_Iterator it;
-   unsigned int i;
-   const Efl_Net_Ip_Address *o;
-
    mark_point();
 
-   if (ctx->results)
-     {
-        EINA_ARRAY_ITER_NEXT(ctx->results, i, o, it)
-          efl_unref(o);
-        eina_array_free(ctx->results);
-        ctx->results = NULL;
-     }
+   if (ctx->results) eina_value_free(ctx->results);
+   ctx->results = NULL;
 
    ctx->err = 0;
    eina_stringshare_replace(&ctx->canonical_name, NULL);
    eina_stringshare_replace(&ctx->request_address, NULL);
 
-   if (ctx->future)
-     {
-        efl_future_cancel(ctx->future);
-        ctx->future = NULL;
-     }
+   if (ctx->future) eina_future_cancel(ctx->future);
+   ctx->future = NULL;
 }
 
 static Eina_Bool
 _resolve_found(const struct resolve_ctx *ctx, const char *string)
 {
-   Eina_Array_Iterator it;
-   unsigned int i;
    const Efl_Net_Ip_Address *o;
+   unsigned int i, len;
 
    ck_assert_ptr_ne(ctx->results, NULL);
 
-   EINA_ARRAY_ITER_NEXT(ctx->results, i, o, it)
+   EINA_VALUE_ARRAY_FOREACH(ctx->results, len, i, o)
      {
         if (strcmp(string, efl_net_ip_address_string_get(o)) == 0)
           return EINA_TRUE;
@@ -186,8 +173,7 @@ static void
 _assert_found_internal(const char *file, int line, const struct resolve_ctx *ctx, const char *string, Eina_Bool expected, Eina_Error err)
 {
    Eina_Bool found;
-   Eina_Array_Iterator it;
-   unsigned int i;
+   unsigned int i, len;
    const Efl_Net_Ip_Address *o;
 
    if (ctx->err != err)
@@ -206,7 +192,7 @@ _assert_found_internal(const char *file, int line, const struct resolve_ctx *ctx
    fprintf(stderr, "ERROR: did%s expect '%s' in results:\n",
            expected ? "" : " NOT", string);
 
-   EINA_ARRAY_ITER_NEXT(ctx->results, i, o, it)
+   EINA_VALUE_ARRAY_FOREACH(ctx->results, len, i, o)
      fprintf(stderr, "result %u: %s\n", i, efl_net_ip_address_string_get(o));
 
    _ck_assert_failed(file, line, "Failed",
@@ -216,44 +202,35 @@ _assert_found_internal(const char *file, int line, const struct resolve_ctx *ctx
                      NULL);
 }
 
-static void
-_resolve_done(void *data, const Efl_Event *event)
+static Eina_Value
+_resolve_done(void *data, const Eina_Value v, const Eina_Future *dead_future EINA_UNUSED)
 {
    struct resolve_ctx *ctx = data;
-   Efl_Future_Event_Success *f = event->info;
-   Efl_Net_Ip_Address_Resolve_Results *r = f->value;
-   Eina_Array_Iterator it;
-   unsigned int i;
-   Efl_Net_Ip_Address *o;
-
-   ck_assert_ptr_eq(ctx->results, NULL);
-   ctx->results = eina_array_new(32);
-
-   ctx->canonical_name = eina_stringshare_ref(r->canonical_name);
-   ctx->request_address = eina_stringshare_ref(r->request_address);
+   const Eina_Value_Array desc = { 0 };
 
-   EINA_ARRAY_ITER_NEXT(r->results, i, o, it)
-     eina_array_push(ctx->results, efl_ref(o));
+   mark_point();
 
-   ctx->future = NULL;
-   ecore_main_loop_quit();
+   if (eina_value_type_get(&v) == EINA_VALUE_TYPE_ERROR)
+     {
+        eina_value_error_get(&v, &ctx->err);
+        goto end;
+     }
 
-   mark_point();
-}
+   eina_value_struct_get(&v, "canonical_name", &ctx->canonical_name);
+   eina_value_struct_get(&v, "request_address", &ctx->request_address);
+   eina_value_struct_get(&v, "results", &desc);
 
-static void
-_resolve_failed(void *data, const Efl_Event *event)
-{
-   struct resolve_ctx *ctx = data;
-   Efl_Future_Event_Failure *f = event->info;
+   ctx->results = eina_value_new(EINA_VALUE_TYPE_ARRAY);
+   eina_value_pset(ctx->results, &desc);
 
-   mark_point();
+ end:
+   ecore_main_loop_quit();
 
-   ctx->err = f->error;
    ctx->future = NULL;
-   ecore_main_loop_quit();
 
    mark_point();
+
+   return v;
 }
 
 static void
@@ -262,7 +239,7 @@ _resolve(struct resolve_ctx *ctx, const char *address, int family, int flags)
    ctx->future = efl_net_ip_address_resolve(EFL_NET_IP_ADDRESS_CLASS,
                                             address, family, flags);
    ck_assert_ptr_ne(ctx->future, NULL);
-   efl_future_then(ctx->future, _resolve_done, _resolve_failed, NULL, ctx);
+   ctx->future = eina_future_then(ctx->future, _resolve_done, ctx);
 
    LOOP_WITH_TIMEOUT(10);
 }