diff --git a/reference/c/eina/src/eina_future.c b/reference/c/eina/src/eina_future.c new file mode 100644 index 00000000..006e063d --- /dev/null +++ b/reference/c/eina/src/eina_future.c @@ -0,0 +1,244 @@ +#define EFL_EO_API_SUPPORT 1 +#define EFL_BETA_API_SUPPORT 1 + +#include +#include +#include + +#include +#include + +/* + * Eina Future examples. + * + * TODO + */ + +#define DEFAULT_MSG "the simple example is working!" + +#define VALUE_TYPE_CHECK(_v, _type) \ + if (_v.type != _type) \ + { \ + fprintf(stderr, "Value type is not '%s' - received '%s'\n", \ + _type->name, _v.type->name); \ + return _v; \ + } + +typedef struct _Ctx { + Eina_Promise *p; + Eina_Bool should_fail; + Ecore_Timer *timer; + Eina_Value *value; +} Ctx; + +static void +_promise_cancel(void *data, const Eina_Promise *dead EINA_UNUSED) +{ + Ctx *ctx = data; + if (ctx->timer) efl_del(ctx->timer); + eina_value_free(ctx->value); + free(ctx); +} + +static Ctx * +_promise_ctx_new(Eina_Value *v) +{ + Ctx *ctx; + Efl_Loop *loop; + ctx = calloc(1, sizeof(Ctx)); + EINA_SAFETY_ON_NULL_GOTO(ctx, err_ctx); + + loop = efl_loop_main_get(EFL_LOOP_CLASS); + ctx->p = eina_promise_new(efl_loop_future_scheduler_get(loop), + _promise_cancel, ctx); + EINA_SAFETY_ON_NULL_GOTO(ctx->p, err_timer); + ctx->value = v; + return ctx; + err_timer: + free(ctx); + err_ctx: + eina_value_free(v); + return NULL; +} + +static void +_timeout(void *data, const Efl_Event *event EINA_UNUSED) +{ + Ctx *ctx = data; + + if (ctx->should_fail) + { + eina_promise_reject(ctx->p, ENETDOWN); + } + else + { + Eina_Value v; + eina_value_copy(ctx->value, &v); + eina_promise_resolve(ctx->p, v); + eina_value_free(ctx->value); + } + + efl_del(ctx->timer); + free(ctx); +} + +static Eina_Future * +_future_get(Ctx *ctx) +{ + Eina_Future *f; + + f = eina_future_new(ctx->p); + EINA_SAFETY_ON_NULL_GOTO(f, err_future); + + efl_add(EFL_LOOP_TIMER_CLASS, NULL, + ctx->timer = efl_added, + efl_loop_timer_interval_set(efl_added, 0.1), + efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TICK, _timeout, ctx)); + + EINA_SAFETY_ON_NULL_GOTO(ctx->timer, err_timer); + return f; + + err_timer: + eina_future_cancel(f); + err_future: + return NULL; +} + +static Eina_Future * +_fail_future_get(void) +{ + Ctx *ctx = _promise_ctx_new(NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); + ctx->should_fail = EINA_TRUE; + return _future_get(ctx); +} + +static Eina_Future * +_str_future_get(void) +{ + Eina_Value *v = eina_value_util_string_new(DEFAULT_MSG); + EINA_SAFETY_ON_NULL_RETURN_VAL(v, NULL); + Ctx *ctx = _promise_ctx_new(v); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); + return _future_get(ctx); +} + +static Eina_Value +_simple_ok(void *data EINA_UNUSED, const Eina_Value v, const Eina_Future *dead_future EINA_UNUSED) +{ + VALUE_TYPE_CHECK(v, EINA_VALUE_TYPE_STRING); + return v; +} + +static Eina_Value +_simple_err(void *data EINA_UNUSED, const Eina_Value v, const Eina_Future *dead_future EINA_UNUSED) +{ + VALUE_TYPE_CHECK(v, EINA_VALUE_TYPE_ERROR); + return v; +} + +static void +_simple(void) +{ + eina_future_chain(_str_future_get(), + eina_future_cb_console("Expecting the following message: "DEFAULT_MSG "\n Got: ", NULL), + { .cb = _simple_ok, .data = NULL }); + eina_future_chain(_fail_future_get(), + eina_future_cb_console("Expecting network down error\n Got: ", NULL), + { .cb = _simple_err, .data = NULL }); +} + +static Eina_Future * +_int_future_get(void) +{ + Eina_Value *v = eina_value_util_int_new(1); + EINA_SAFETY_ON_NULL_RETURN_VAL(v, NULL); + Ctx *ctx = _promise_ctx_new(v); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); + return _future_get(ctx); +} + +static Eina_Value +_chain_no_errors_cb(void *data EINA_UNUSED, const Eina_Value v, const Eina_Future *dead_future EINA_UNUSED) +{ + int val; + + VALUE_TYPE_CHECK(v, EINA_VALUE_TYPE_INT); + eina_value_get(&v, &val); + + return *eina_value_util_int_new(val * 2); +} + +static Eina_Value +_exit_cb(void *data EINA_UNUSED, const Eina_Value v, const Eina_Future *dead_future EINA_UNUSED) +{ + efl_exit(0); + + return v; +} + +static void +_chain_no_errors(void) +{ + eina_future_chain(_int_future_get(), + eina_future_cb_console("Expecting number 1\n Got: ", NULL), + {.cb = _chain_no_errors_cb, .data = NULL}, + eina_future_cb_console("Expecting number 2\n Got: ", NULL), + {.cb = _chain_no_errors_cb, .data = NULL}, + eina_future_cb_console("Expecting number 4\n Got: ", NULL), + {.cb = _chain_no_errors_cb, .data = NULL}, + eina_future_cb_console("Expecting number 8\n Got: ", NULL), + {.cb = _chain_no_errors_cb, .data = NULL}, + eina_future_cb_console("Expecting number 16\n Got: ", NULL), + {.cb = _exit_cb, .data = NULL}); +} + +static Eina_Value +_chain_with_error_cb(void *data EINA_UNUSED, const Eina_Value v EINA_UNUSED, const Eina_Future *dead_future EINA_UNUSED) +{ + Eina_Value err; + eina_value_setup(&err, EINA_VALUE_TYPE_ERROR); + eina_value_set(&err, E2BIG); + return err; +} + +static void +_chain_with_error(void) +{ + eina_future_chain(_int_future_get(), + { .cb=_chain_with_error_cb, .data=NULL }, + eina_future_cb_console("Expecting argument list too long. Got: ", NULL), + { .cb = _simple_err, .data = NULL }); + } + +static Eina_Value +_canceled_cb(void *data EINA_UNUSED, const Eina_Value v, const Eina_Future *dead_future EINA_UNUSED) +{ + VALUE_TYPE_CHECK(v, EINA_VALUE_TYPE_ERROR); + return v; +} + +static void +_future_cancel(void) +{ + Eina_Future *f; + + f = eina_future_chain(_int_future_get(), + eina_future_cb_console("Expecting cancelled operation error. Got: ", NULL), + { .cb = _canceled_cb, .data = NULL }, + eina_future_cb_console("Expecting cancelled operation error. Got: ", NULL), + { .cb = _canceled_cb, .data = NULL }, + eina_future_cb_console("Expecting cancelled operation error. Got: ", NULL)); + eina_future_cancel(f); +} + +EAPI_MAIN void +efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED) +{ + _simple(); + _chain_no_errors(); + _chain_with_error(); + _future_cancel(); +} + +EFL_MAIN() diff --git a/reference/c/eina/src/meson.build b/reference/c/eina/src/meson.build index 04d998b9..740bbb32 100644 --- a/reference/c/eina/src/meson.build +++ b/reference/c/eina/src/meson.build @@ -49,6 +49,13 @@ executable('efl_reference_eina_value_custom', install : true ) +executable('efl_reference_eina_future', + files(['eina_future.c']), + dependencies : deps, + include_directories : inc, + install : true +) + executable('efl_reference_eina_log', files(['eina_log.c']), dependencies : deps,