ajwillia-ms pushed a commit to branch master.

http://git.enlightenment.org/tools/examples.git/commit/?id=af48dd8fbae879b237360bfe4e77fd12eb15174b

commit af48dd8fbae879b237360bfe4e77fd12eb15174b
Author: Andy Williams <a...@andywilliams.me>
Date:   Wed Dec 13 12:23:39 2017 +0000

    eina: simplify and document our futures example
---
 reference/c/eina/src/eina_future.c | 333 +++++++++++++++++++------------------
 1 file changed, 168 insertions(+), 165 deletions(-)

diff --git a/reference/c/eina/src/eina_future.c 
b/reference/c/eina/src/eina_future.c
index 006e063..7e483af 100644
--- a/reference/c/eina/src/eina_future.c
+++ b/reference/c/eina/src/eina_future.c
@@ -14,231 +14,234 @@
  * 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;
-
+/*
+ * This will be called if a promise is cancelled
+ */
 static void
-_promise_cancel(void *data, const Eina_Promise *dead EINA_UNUSED)
+_promise_cancel(void *data EINA_UNUSED, const Eina_Promise *dead EINA_UNUSED)
 {
-   Ctx *ctx = data;
-   if (ctx->timer) efl_del(ctx->timer);
-   eina_value_free(ctx->value);
-   free(ctx);
+   printf("Promise cancelled\n");
 }
 
-static Ctx *
-_promise_ctx_new(Eina_Value *v)
+/*
+ * This simple method prints the content of a value and passes it on
+ */
+static Eina_Value
+_value_print(void *data EINA_UNUSED, const Eina_Value value)
 {
-   Ctx *ctx;
-   Efl_Loop *loop;
-   ctx = calloc(1, sizeof(Ctx));
-   EINA_SAFETY_ON_NULL_GOTO(ctx, err_ctx);
+   printf("Found value %s\n", eina_value_to_string(&value));
 
-   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;
+   return value;
 }
 
-static void
-_timeout(void *data, const Efl_Event *event EINA_UNUSED)
+/*
+ * This method will resolve the passed promise with a string value
+ */
+static Eina_Value
+_delayed_value_resolve(void *data, const Eina_Value value EINA_UNUSED)
 {
-   Ctx *ctx = data;
+   Eina_Promise *promise;
 
-   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);
-     }
+   promise = (Eina_Promise *)data;
+   eina_promise_resolve(promise, eina_value_string_init("Delayed Value :)"));
 
-   efl_del(ctx->timer);
-   free(ctx);
+   return EINA_VALUE_EMPTY;
 }
 
-static Eina_Future *
-_future_get(Ctx *ctx)
+/*
+ * A simple future demo, set up a promised future
+ * and resolve it from a timer future.
+ */
+static void
+_simple_future()
 {
-   Eina_Future *f;
-
-   f = eina_future_new(ctx->p);
-   EINA_SAFETY_ON_NULL_GOTO(f, err_future);
+   Efl_Loop *loop;
+   Eina_Promise *promise;
 
-   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));
+   // Create a demo promise for the sake of a trivial demo
+   loop = efl_loop_main_get(EFL_LOOP_CLASS);
+   promise = eina_promise_new(efl_loop_future_scheduler_get(loop), 
_promise_cancel, NULL);
 
-   EINA_SAFETY_ON_NULL_GOTO(ctx->timer, err_timer);
-   return f;
+   // Tis future will trigger a _value_print once resolved
+   eina_future_then_easy(eina_future_new(promise), .success = _value_print);
 
- err_timer:
-   eina_future_cancel(f);
- err_future:
-   return NULL;
+   // This future is basically a timer - wait 100ms and then resolve the 
promise above
+   eina_future_then_easy(efl_loop_timeout(efl_loop_main_get(EFL_LOOP_CLASS), 
0.1),
+                         .success = _delayed_value_resolve, .data = promise);
 }
 
-static Eina_Future *
-_fail_future_get(void)
+/*
+ * This method prints the message of the error encountered and returns no 
value.
+ */
+static Eina_Value
+_error_print(void *data EINA_UNUSED, const Eina_Error error)
 {
-   Ctx *ctx = _promise_ctx_new(NULL);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
-   ctx->should_fail = EINA_TRUE;
-   return _future_get(ctx);
+   printf("Encountered error %s\n", eina_error_msg_get(error));
+
+   return EINA_VALUE_EMPTY;
 }
 
-static Eina_Future *
-_str_future_get(void)
+/*
+ * This method will reject the passed promise with a "magic" error.
+ */
+static Eina_Value
+_delayed_value_reject(void *data, const Eina_Value value EINA_UNUSED)
 {
-   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);
+   Eina_Promise *promise;
+
+   promise = (Eina_Promise *)data;
+   eina_promise_reject(promise, EINA_ERROR_MAGIC_FAILED);
+
+   return EINA_VALUE_EMPTY;
 }
 
-static Eina_Value
-_simple_ok(void *data EINA_UNUSED, const Eina_Value v, const Eina_Future 
*dead_future EINA_UNUSED)
+/*
+ * A simple future failed demo, set up a promised future
+ * and reject it from a timer future.
+ */
+static void
+_failed_future()
 {
-   VALUE_TYPE_CHECK(v, EINA_VALUE_TYPE_STRING);
-   return v;
+   Efl_Loop *loop;
+   Eina_Promise *promise;
+
+   // Create a demo promise for the sake of a trivial demo
+   loop = efl_loop_main_get(EFL_LOOP_CLASS);
+   promise = eina_promise_new(efl_loop_future_scheduler_get(loop), 
_promise_cancel, NULL);
+
+   // Tis future will trigger a _value_print once resolved
+   eina_future_then_easy(eina_future_new(promise), .error = _error_print);
+
+   // This future is basically a timer - wait 100ms and then resolve the 
promise above
+   eina_future_then_easy(efl_loop_timeout(efl_loop_main_get(EFL_LOOP_CLASS), 
0.1),
+                         .success = _delayed_value_reject, .data = promise);
 }
 
-static Eina_Value
-_simple_err(void *data EINA_UNUSED, const Eina_Value v, const Eina_Future 
*dead_future EINA_UNUSED)
+/*
+ * A simple future failed demo, set up a promised future
+ * and reject it from a timer future.
+ */
+static void
+_cancel_future()
 {
-   VALUE_TYPE_CHECK(v, EINA_VALUE_TYPE_ERROR);
-   return v;
+   Efl_Loop *loop;
+   Eina_Promise *promise;
+   Eina_Future *future;
+
+   // Create a demo promise for the sake of a trivial demo
+   loop = efl_loop_main_get(EFL_LOOP_CLASS);
+   promise = eina_promise_new(efl_loop_future_scheduler_get(loop), 
_promise_cancel, NULL);
+   future = eina_future_new(promise);
+
+   // Tis future will trigger a _value_print once resolved
+   eina_future_then_easy(future, .success = _value_print);
+
+   // Then we cancel the future before it has a chance to resolve
+   eina_future_cancel(future);
 }
 
+/*
+ * When our timeout is triggered we will resolve the promise passed.
+ * Set an int value to initialise the chain.
+ */
 static void
-_simple(void)
+_timeout(void *data, const Efl_Event *event)
 {
-   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 });
+   Eina_Promise *promise;
+
+   promise = data;
+   eina_promise_resolve(promise, eina_value_int_init(1));
+
+   efl_del(event->object);
 }
 
+/*
+ * Create a new int future that will resolve after a specified timer delay.
+ */
 static Eina_Future *
-_int_future_get(void)
+_delayed_int_future_get(double delay)
 {
-   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);
+   Efl_Loop *loop;
+   Eina_Promise *promise;
+
+   // Create a demo promise for the sake of a trivial demo
+   loop = efl_loop_main_get(EFL_LOOP_CLASS);
+   promise = eina_promise_new(efl_loop_future_scheduler_get(loop),
+                              _promise_cancel, NULL);
+
+   efl_add(EFL_LOOP_TIMER_CLASS, NULL,
+           efl_loop_timer_interval_set(efl_added, delay),
+           efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TICK,
+                                  _timeout, promise));
+
+   return eina_future_new(promise);
 }
 
+/*
+ * A value callback to chain, taking in an int value and returning to chain
+ * the int multiplied by two.
+ */
 static Eina_Value
-_chain_no_errors_cb(void *data EINA_UNUSED, const Eina_Value v, const 
Eina_Future *dead_future EINA_UNUSED)
+_chain_multiply_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);
+   if (v.type != EINA_VALUE_TYPE_INT)
+     {
+        fprintf(stderr, "Incorrect type was returned");
+        return v;
+     }
 
+   eina_value_get(&v, &val);
    return *eina_value_util_int_new(val * 2);
 }
 
+/*
+ * This chained callback exits our example.
+ */
 static Eina_Value
-_exit_cb(void *data EINA_UNUSED, const Eina_Value v, const Eina_Future 
*dead_future EINA_UNUSED)
+_exit_cb(void *data EINA_UNUSED, const Eina_Value v EINA_UNUSED,
+         const Eina_Future *dead_future EINA_UNUSED)
 {
    efl_exit(0);
 
-   return v;
+   return EINA_VALUE_EMPTY;
 }
 
+/*
+ * Run a future chain where the initial future returns a single value.
+ * Each item in the chain then processes this value and passes on another.
+ * The _chain_multiply_cb returns twice the value it gets and the
+ * eina_future_cb_console prints a message including the value before passing
+ * it on.
+ */
 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),
+_chained_future(void)
+{
+   eina_future_chain(_delayed_int_future_get(0.1),
+                     eina_future_cb_console("Starting chain with: ", NULL),
+                     {.cb = _chain_multiply_cb, .data = NULL},
+                     eina_future_cb_console("  Multiplied by 2: ", NULL),
+                     {.cb = _chain_multiply_cb, .data = NULL},
+                     eina_future_cb_console("  Multiplied by 2: ", NULL),
+                     {.cb = _chain_multiply_cb, .data = NULL},
+                     eina_future_cb_console("  Multiplied by 2: ", NULL),
+                     {.cb = _chain_multiply_cb, .data = NULL},
+                     eina_future_cb_console("  Multiplied by 2: ", 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);
-}
-
+/*
+ * Run some futures examples.
+ */
 EAPI_MAIN void
 efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
 {
-   _simple();
-   _chain_no_errors();
-   _chain_with_error();
-   _future_cancel();
+   _simple_future();
+   _failed_future();
+   _cancel_future();
+   _chained_future();
 }
 
 EFL_MAIN()

-- 


Reply via email to