#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()