From 9ca1075f713500545ee786e378008010b1ada3bb Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Fri, 27 Apr 2018 16:20:47 -0700 Subject: [PATCH] ecore_con: migrate efl_net_ip_address_resolve to use Eina_Future. --- src/lib/ecore_con/efl_net_ip_address.c | 172 ++++++++++++--------- src/lib/ecore_con/efl_net_ip_address.eo | 2 +- .../ecore_con/ecore_con_test_efl_net_ip_address.c | 81 ++++------ 3 files changed, 127 insertions(+), 128 deletions(-) diff --git a/src/lib/ecore_con/efl_net_ip_address.c b/src/lib/ecore_con/efl_net_ip_address.c index 802cd20..097d233 100644 --- a/src/lib/ecore_con/efl_net_ip_address.c +++ b/src/lib/ecore_con/efl_net_ip_address.c @@ -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); diff --git a/src/lib/ecore_con/efl_net_ip_address.eo b/src/lib/ecore_con/efl_net_ip_address.eo index e715a0c..dfb9953 100644 --- a/src/lib/ecore_con/efl_net_ip_address.eo +++ b/src/lib/ecore_con/efl_net_ip_address.eo @@ -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; [[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 { diff --git a/src/tests/ecore_con/ecore_con_test_efl_net_ip_address.c b/src/tests/ecore_con/ecore_con_test_efl_net_ip_address.c index a32f6ee..b44bd0b 100644 --- a/src/tests/ecore_con/ecore_con_test_efl_net_ip_address.c +++ b/src/tests/ecore_con/ecore_con_test_efl_net_ip_address.c @@ -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); } -- 2.7.4