aboutsummaryrefslogtreecommitdiffstats
path: root/reference
diff options
context:
space:
mode:
authorXavi Artigas <xavierartigas@yahoo.es>2018-01-02 16:26:03 +0100
committerXavi Artigas <xavierartigas@yahoo.es>2018-01-02 16:26:03 +0100
commit11091214f782ccb5f9bed53ca83deccda1626ccc (patch)
tree0648985674c4fb7a4708a31446af1432b364a443 /reference
parenteina: use a timer instead of another future for our first example (diff)
downloadexamples-11091214f782ccb5f9bed53ca83deccda1626ccc.tar.gz
Overhaul of the Eina_Future example
Run tests consecutively, triggering next one on the future's free callback. Label test numbers explicitly, code reordering and beautifying. Some console output beautifying too.
Diffstat (limited to 'reference')
-rw-r--r--reference/c/eina/src/eina_future.c295
1 files changed, 172 insertions, 123 deletions
diff --git a/reference/c/eina/src/eina_future.c b/reference/c/eina/src/eina_future.c
index 10c52fa2..55f6ebf8 100644
--- a/reference/c/eina/src/eina_future.c
+++ b/reference/c/eina/src/eina_future.c
@@ -9,220 +9,265 @@
#include <Efl_Core.h>
/*
- * Eina Future examples.
- *
- * TODO
+ * A collection of Eina Future examples.
+ * TEST 1: Set up a promised future and resolve it from a timer callback.
+ * TEST 2: Set up a promised future and reject it from a timer callback.
+ * TEST 3: Set up a promised future and then cancel it.
+ * TEST 4: Set up a chain of futures that get called one after the other when
+ * the promise is resolved, passing a value among them.
*/
+static void _test1_simple_future();
+static void _test2_failed_future();
+static void _test3_cancelled_future();
+static void _test4_chained_future();
+
+/* ----------------------- Generic helper methods ---------------------- */
+
+/*
+ * This simple method prints the content of a value and passes it on.
+ */
+static Eina_Value
+_value_print(void *data, const Eina_Value value)
+{
+ Eina_Promise *promise = (Eina_Promise *)data;
+ char *str = eina_value_to_string(&value);
+ printf(" Success callback: Promise %p resolved to '%s'\n", promise, str);
+ free(str);
+
+ return value;
+}
+
/*
- * This will be called if a promise is cancelled
+ * This will be called if a promise is cancelled.
*/
static void
_promise_cancel(void *data EINA_UNUSED, const Eina_Promise *dead EINA_UNUSED)
{
- printf("Promise cancelled\n");
+ printf(" Promise cancellation callback: Promise %p cancelled\n", dead);
}
/*
- * This simple method prints the content of a value and passes it on
+ * This method prints the message of the error encountered and returns no value.
*/
static Eina_Value
-_value_print(void *data EINA_UNUSED, const Eina_Value value)
+_error_print(void *data EINA_UNUSED, const Eina_Error error)
{
- printf("Found value %s\n", eina_value_to_string(&value));
+ Eina_Promise *promise = (Eina_Promise *)data;
+ printf(" Error callback: Promise %p encountered error '%s'\n", promise,
+ eina_error_msg_get(error));
- return value;
+ return EINA_VALUE_EMPTY;
}
-/*
- * This method will resolve the passed promise with a string value
- */
+/* ----------------------- Test 1 ---------------------- */
+
+/* Resolve the promise passed through data to a string and cancel the timer */
static void
-_delayed_value_resolve(void *data, const Efl_Event *event)
+_test1_resolve(void *data, const Efl_Event *event)
{
- Eina_Promise *promise;
+ Eina_Promise *promise = (Eina_Promise *)data;
- promise = (Eina_Promise *)data;
- eina_promise_resolve(promise, eina_value_string_init("Delayed Value :)"));
+ eina_promise_resolve(promise, eina_value_string_init("Test 1 Delayed Value"));
efl_del(event->object);
}
-/*
- * A simple future demo, set up a promised future
- * and resolve it from a timer future.
- */
+/* Launches the next test */
+static void
+_test1_next_test(void *data EINA_UNUSED, const Eina_Future *dead_future EINA_UNUSED)
+{
+ printf(" Test 1 finished\n");
+ _test2_failed_future();
+}
+
+/* TEST 1: Set up a promised future and resolve it from a timer callback */
static void
-_simple_future()
+_test1_simple_future()
{
Efl_Loop *loop;
Eina_Promise *promise;
- // Create a demo promise for the sake of a trivial demo
+ // Create a promise
loop = efl_loop_main_get(EFL_LOOP_CLASS);
- promise = eina_promise_new(efl_loop_future_scheduler_get(loop), _promise_cancel, NULL);
+ promise = eina_promise_new(efl_loop_future_scheduler_get(loop),
+ _promise_cancel, NULL);
+ printf("Test 1: Waiting for promise %p to be resolved...\n", promise);
- // Tis future will trigger a _value_print once resolved
- eina_future_then_easy(eina_future_new(promise), .success = _value_print);
+ // This future will call _value_print() when the promise is resolved and
+ // execute the next test when the future is destroyed (for whatever reason)
+ eina_future_then_easy(eina_future_new(promise),
+ .success = _value_print,
+ .free = _test1_next_test,
+ .data = promise);
- // This future is basically a timer - wait 100ms and then resolve the promise above
+ // Set up a regular timer that will trigger after 1s. We use it to
+ // simulate a delayed promise resolve.
efl_add(EFL_LOOP_TIMER_CLASS, loop,
- efl_loop_timer_interval_set(efl_added, 0.1),
+ efl_loop_timer_interval_set(efl_added, 1),
efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TICK,
- _delayed_value_resolve, promise));
+ _test1_resolve, promise));
}
-/*
- * 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)
-{
- printf("Encountered error %s\n", eina_error_msg_get(error));
-
- return EINA_VALUE_EMPTY;
-}
+/* ----------------------- Test 2 ---------------------- */
-/*
- * 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)
+/* Reject the passed promise with an specific error and cancel the timer */
+static void
+_test2_reject(void *data, const Efl_Event *event)
{
- Eina_Promise *promise;
+ Eina_Promise *promise = (Eina_Promise *)data;
- promise = (Eina_Promise *)data;
eina_promise_reject(promise, EINA_ERROR_NOT_IMPLEMENTED);
- return EINA_VALUE_EMPTY;
+ efl_del(event->object);
}
-/*
- * A simple future failed demo, set up a promised future
- * and reject it from a timer future.
- */
+/* Launches the next test */
+static void
+_test2_next_test(void *data EINA_UNUSED, const Eina_Future *dead_future EINA_UNUSED)
+{
+ printf(" Test 2 finished\n");
+ _test3_cancelled_future();
+}
+
+/* TEST 2: Set up a promised future and reject it from a timer callback */
static void
-_failed_future()
+_test2_failed_future()
{
Efl_Loop *loop;
Eina_Promise *promise;
- // Create a demo promise for the sake of a trivial demo
+ // Create a promise
loop = efl_loop_main_get(EFL_LOOP_CLASS);
- promise = eina_promise_new(efl_loop_future_scheduler_get(loop), _promise_cancel, NULL);
+ promise = eina_promise_new(efl_loop_future_scheduler_get(loop),
+ _promise_cancel, NULL);
+ printf("Test 2: Waiting for promise %p to be rejected...\n", promise);
+
+ // This future will call _value_print() when the promise is resolved.
+ // If there is an error, _error_print() is called instead.
+ // It then executes the next test when the future is destroyed.
+ eina_future_then_easy(eina_future_new(promise),
+ .success = _value_print,
+ .error = _error_print,
+ .free = _test2_next_test,
+ .data = promise);
+
+ // Set up a regular timer that will trigger after 1s. We use it to
+ // simulate a delayed promise rejection.
+ efl_add(EFL_LOOP_TIMER_CLASS, loop,
+ efl_loop_timer_interval_set(efl_added, 1),
+ efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TICK,
+ _test2_reject, promise));
+}
- // Tis future will trigger a _value_print once resolved
- eina_future_then_easy(eina_future_new(promise), .error = _error_print);
+/* ----------------------- Test 3 ---------------------- */
- // 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.2),
- .success = _delayed_value_reject, .data = promise);
+/* Launches the next test */
+static void
+_test3_next_test(void *data EINA_UNUSED, const Eina_Future *dead_future EINA_UNUSED)
+{
+ printf(" Test 3 finished\n");
+ _test4_chained_future();
}
-/*
- * A simple future failed demo, set up a promised future
- * and reject it from a timer future.
- */
+/* TEST 3: Set up a promised future and then cancel it */
static void
-_cancel_future()
+_test3_cancelled_future()
{
Efl_Loop *loop;
Eina_Promise *promise;
Eina_Future *future;
- // Create a demo promise for the sake of a trivial demo
+ // Create a promise
loop = efl_loop_main_get(EFL_LOOP_CLASS);
- promise = eina_promise_new(efl_loop_future_scheduler_get(loop), _promise_cancel, NULL);
+ 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
+ printf("Test 3: Waiting for promise %p to be cancelled...\n", promise);
+
+ // This future will call _value_print() when the promise is resolved.
+ // If there is an error, _error_print() is called instead.
+ // It then executes the next test when the future is destroyed.
+ eina_future_then_easy(future,
+ .success = _value_print,
+ .error = _error_print,
+ .free = _test3_next_test,
+ .data = promise);
+
+ // 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.
- */
+/* ----------------------- Test 4 ---------------------- */
+
+/* Resolve the passed promise to an integer with value 1 and cancel the timer */
static void
-_timeout(void *data, const Efl_Event *event)
+_test4_resolve(void *data, const Efl_Event *event)
{
- Eina_Promise *promise;
+ Eina_Promise *promise = (Eina_Promise *)data;
- 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 *
-_delayed_int_future_get(double delay)
-{
- 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, loop,
- 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_multiply_cb(void *data EINA_UNUSED, const Eina_Value v,
+_chain_multiply_cb(void *data EINA_UNUSED, const Eina_Value value,
const Eina_Future *dead_future EINA_UNUSED)
{
- int val;
+ int i;
- if (v.type != EINA_VALUE_TYPE_INT)
+ if (value.type != EINA_VALUE_TYPE_INT)
{
- fprintf(stderr, "Incorrect type was returned");
- return v;
+ fprintf(stderr, "Expected type 'int', got '%s'\n", value.type->name);
+ return value;
}
- eina_value_get(&v, &val);
- return *eina_value_util_int_new(val * 2);
+ eina_value_get(&value, &i);
+ return *eina_value_util_int_new(i * 2);
}
-/*
- * This chained callback exits our example.
- */
+/* This chained callback exits the example */
static Eina_Value
-_exit_cb(void *data EINA_UNUSED, const Eina_Value v EINA_UNUSED,
+_exit_cb(void *data EINA_UNUSED, const Eina_Value value EINA_UNUSED,
const Eina_Future *dead_future EINA_UNUSED)
{
efl_exit(0);
+ printf(" Test 4 finished\n");
+
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
+ * TEST 4: Run a future chain where the initial future returns a single value.
+ * Each item in the chain then processes this value and passes it to the next item.
+ * 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
-_chained_future(void)
+_test4_chained_future(void)
{
- eina_future_chain(_delayed_int_future_get(0.5),
- eina_future_cb_console("Starting chain with: ", NULL),
+ Efl_Loop *loop;
+ Eina_Promise *promise;
+
+ // Create a promise
+ loop = efl_loop_main_get(EFL_LOOP_CLASS);
+ promise = eina_promise_new(efl_loop_future_scheduler_get(loop),
+ _promise_cancel, NULL);
+
+ printf("Test 4: Waiting for promise %p to be resolved...\n", promise);
+ // All these methods, eina_future_cb_console() and _chain_multiply_cb(), will
+ // be called one after the other when the promise is resolved.
+ // Note how the last one is _exit_cb().
+ // There are 10 futures chained in total.
+ eina_future_chain(eina_future_new(promise),
+ eina_future_cb_console(" Starting chain with value: ", NULL),
{.cb = _chain_multiply_cb, .data = NULL},
eina_future_cb_console(" Multiplied by 2: ", NULL),
{.cb = _chain_multiply_cb, .data = NULL},
@@ -232,18 +277,22 @@ _chained_future(void)
{.cb = _chain_multiply_cb, .data = NULL},
eina_future_cb_console(" Multiplied by 2: ", NULL),
{.cb = _exit_cb, .data = NULL});
+
+ // Set up a regular timer that will trigger after 1s. We use it to
+ // simulate a delayed promise resolve.
+ efl_add(EFL_LOOP_TIMER_CLASS, loop,
+ efl_loop_timer_interval_set(efl_added, 1),
+ efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TICK,
+ _test4_resolve, promise));
}
-/*
- * Run some futures examples.
- */
+/* ----------------------- Main ---------------------- */
+
EAPI_MAIN void
efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
{
- _simple_future();
- _failed_future();
- _cancel_future();
- _chained_future();
+ // Start the first test, the others will be launched when this one finishes
+ _test1_simple_future();
}
EFL_MAIN()