2017-12-12 11:37:56 -08:00
|
|
|
#define EFL_EO_API_SUPPORT 1
|
|
|
|
#define EFL_BETA_API_SUPPORT 1
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include <Eina.h>
|
|
|
|
#include <Efl_Core.h>
|
|
|
|
|
|
|
|
/*
|
2018-01-02 07:26:03 -08:00
|
|
|
* 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.
|
2017-12-12 11:37:56 -08:00
|
|
|
*/
|
|
|
|
|
2018-01-04 11:28:26 -08:00
|
|
|
static void _test1_simple_future(Efl_Loop *loop);
|
|
|
|
static void _test2_failed_future(Efl_Loop *loop);
|
|
|
|
static void _test3_cancelled_future(Efl_Loop *loop);
|
|
|
|
static void _test4_chained_future(Efl_Loop *loop);
|
2018-01-02 07:26:03 -08:00
|
|
|
|
|
|
|
/* ----------------------- Generic helper methods ---------------------- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This simple method prints the content of a value and passes it on.
|
|
|
|
*/
|
|
|
|
static Eina_Value
|
2018-01-04 11:28:26 -08:00
|
|
|
_value_print(void *data EINA_UNUSED, const Eina_Value value)
|
2018-01-02 07:26:03 -08:00
|
|
|
{
|
|
|
|
char *str = eina_value_to_string(&value);
|
2018-01-04 11:28:26 -08:00
|
|
|
printf(" Success callback: Promise resolved to '%s'\n", str);
|
2018-01-02 07:26:03 -08:00
|
|
|
free(str);
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2017-12-13 04:23:39 -08:00
|
|
|
/*
|
2018-01-02 07:26:03 -08:00
|
|
|
* This will be called if a promise is cancelled.
|
2017-12-13 04:23:39 -08:00
|
|
|
*/
|
2017-12-12 11:37:56 -08:00
|
|
|
static void
|
2017-12-13 04:23:39 -08:00
|
|
|
_promise_cancel(void *data EINA_UNUSED, const Eina_Promise *dead EINA_UNUSED)
|
2017-12-12 11:37:56 -08:00
|
|
|
{
|
2018-01-05 00:22:09 -08:00
|
|
|
printf(" Promise cancellation callback: Promise cancelled\n");
|
2017-12-12 11:37:56 -08:00
|
|
|
}
|
|
|
|
|
2017-12-13 04:23:39 -08:00
|
|
|
/*
|
2018-01-02 07:26:03 -08:00
|
|
|
* This method prints the message of the error encountered and returns no value.
|
2017-12-13 04:23:39 -08:00
|
|
|
*/
|
|
|
|
static Eina_Value
|
2018-01-02 07:26:03 -08:00
|
|
|
_error_print(void *data EINA_UNUSED, const Eina_Error error)
|
2017-12-12 11:37:56 -08:00
|
|
|
{
|
2018-01-04 11:28:26 -08:00
|
|
|
printf(" Error callback: Promise encountered error '%s'\n",
|
2018-01-02 07:26:03 -08:00
|
|
|
eina_error_msg_get(error));
|
2017-12-12 11:37:56 -08:00
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
return EINA_VALUE_EMPTY;
|
2017-12-12 11:37:56 -08:00
|
|
|
}
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
/* ----------------------- Test 1 ---------------------- */
|
|
|
|
|
|
|
|
/* Resolve the promise passed through data to a string and cancel the timer */
|
2017-12-22 04:23:54 -08:00
|
|
|
static void
|
2018-01-02 07:26:03 -08:00
|
|
|
_test1_resolve(void *data, const Efl_Event *event)
|
2017-12-12 11:37:56 -08:00
|
|
|
{
|
2018-01-02 07:26:03 -08:00
|
|
|
Eina_Promise *promise = (Eina_Promise *)data;
|
2017-12-12 11:37:56 -08:00
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
eina_promise_resolve(promise, eina_value_string_init("Test 1 Delayed Value"));
|
2017-12-12 11:37:56 -08:00
|
|
|
|
2017-12-22 04:23:54 -08:00
|
|
|
efl_del(event->object);
|
2017-12-12 11:37:56 -08:00
|
|
|
}
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
/* Launches the next test */
|
|
|
|
static void
|
2018-01-04 11:28:26 -08:00
|
|
|
_test1_next_test(void *data, const Eina_Future *dead_future EINA_UNUSED)
|
2018-01-02 07:26:03 -08:00
|
|
|
{
|
2018-01-04 11:28:26 -08:00
|
|
|
Efl_Loop *loop = data;
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
printf(" Test 1 finished\n");
|
2018-01-04 11:28:26 -08:00
|
|
|
_test2_failed_future(loop);
|
2018-01-02 07:26:03 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* TEST 1: Set up a promised future and resolve it from a timer callback */
|
2017-12-13 04:23:39 -08:00
|
|
|
static void
|
2018-01-04 11:28:26 -08:00
|
|
|
_test1_simple_future(Efl_Loop *loop)
|
2017-12-12 11:37:56 -08:00
|
|
|
{
|
2017-12-13 04:23:39 -08:00
|
|
|
Eina_Promise *promise;
|
2017-12-12 11:37:56 -08:00
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
// Create a promise
|
|
|
|
promise = eina_promise_new(efl_loop_future_scheduler_get(loop),
|
|
|
|
_promise_cancel, NULL);
|
2018-01-05 00:22:09 -08:00
|
|
|
printf("Test 1: Waiting for promise to be resolved...\n");
|
2017-12-12 11:37:56 -08:00
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
// 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,
|
2018-01-04 11:28:26 -08:00
|
|
|
.data = loop);
|
2017-12-12 11:37:56 -08:00
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
// Set up a regular timer that will trigger after 1s. We use it to
|
|
|
|
// simulate a delayed promise resolve.
|
2017-12-22 04:23:54 -08:00
|
|
|
efl_add(EFL_LOOP_TIMER_CLASS, loop,
|
2018-01-02 07:26:03 -08:00
|
|
|
efl_loop_timer_interval_set(efl_added, 1),
|
2019-03-09 06:54:38 -08:00
|
|
|
efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TIMER_TICK,
|
2018-01-02 07:26:03 -08:00
|
|
|
_test1_resolve, promise));
|
2017-12-12 11:37:56 -08:00
|
|
|
}
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
/* ----------------------- Test 2 ---------------------- */
|
2017-12-12 11:37:56 -08:00
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
/* Reject the passed promise with an specific error and cancel the timer */
|
|
|
|
static void
|
|
|
|
_test2_reject(void *data, const Efl_Event *event)
|
2017-12-12 11:37:56 -08:00
|
|
|
{
|
2018-01-02 07:26:03 -08:00
|
|
|
Eina_Promise *promise = (Eina_Promise *)data;
|
2017-12-13 04:23:39 -08:00
|
|
|
|
2017-12-21 08:00:29 -08:00
|
|
|
eina_promise_reject(promise, EINA_ERROR_NOT_IMPLEMENTED);
|
2017-12-13 04:23:39 -08:00
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
efl_del(event->object);
|
2017-12-12 11:37:56 -08:00
|
|
|
}
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
/* Launches the next test */
|
|
|
|
static void
|
2018-01-04 11:28:26 -08:00
|
|
|
_test2_next_test(void *data, const Eina_Future *dead_future EINA_UNUSED)
|
2018-01-02 07:26:03 -08:00
|
|
|
{
|
2018-01-04 11:28:26 -08:00
|
|
|
Efl_Loop *loop = data;
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
printf(" Test 2 finished\n");
|
2018-01-04 11:28:26 -08:00
|
|
|
_test3_cancelled_future(loop);
|
2018-01-02 07:26:03 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* TEST 2: Set up a promised future and reject it from a timer callback */
|
2017-12-13 04:23:39 -08:00
|
|
|
static void
|
2018-01-04 11:28:26 -08:00
|
|
|
_test2_failed_future(Efl_Loop *loop)
|
2017-12-12 11:37:56 -08:00
|
|
|
{
|
2017-12-13 04:23:39 -08:00
|
|
|
Eina_Promise *promise;
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
// Create a promise
|
|
|
|
promise = eina_promise_new(efl_loop_future_scheduler_get(loop),
|
|
|
|
_promise_cancel, NULL);
|
2018-01-05 00:22:09 -08:00
|
|
|
printf("Test 2: Waiting for promise to be rejected...\n");
|
2018-01-02 07:26:03 -08:00
|
|
|
|
|
|
|
// 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,
|
2018-01-04 11:28:26 -08:00
|
|
|
.data = loop);
|
2018-01-02 07:26:03 -08:00
|
|
|
|
|
|
|
// 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),
|
2019-03-09 06:54:38 -08:00
|
|
|
efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TIMER_TICK,
|
2018-01-02 07:26:03 -08:00
|
|
|
_test2_reject, promise));
|
|
|
|
}
|
2017-12-13 04:23:39 -08:00
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
/* ----------------------- Test 3 ---------------------- */
|
2017-12-13 04:23:39 -08:00
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
/* Launches the next test */
|
|
|
|
static void
|
2018-01-04 11:28:26 -08:00
|
|
|
_test3_next_test(void *data, const Eina_Future *dead_future EINA_UNUSED)
|
2018-01-02 07:26:03 -08:00
|
|
|
{
|
2018-01-04 11:28:26 -08:00
|
|
|
Efl_Loop *loop = data;
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
printf(" Test 3 finished\n");
|
2018-01-04 11:28:26 -08:00
|
|
|
_test4_chained_future(loop);
|
2017-12-12 11:37:56 -08:00
|
|
|
}
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
/* TEST 3: Set up a promised future and then cancel it */
|
2017-12-13 04:23:39 -08:00
|
|
|
static void
|
2018-01-04 11:28:26 -08:00
|
|
|
_test3_cancelled_future(Efl_Loop *loop)
|
2017-12-12 11:37:56 -08:00
|
|
|
{
|
2017-12-13 04:23:39 -08:00
|
|
|
Eina_Promise *promise;
|
|
|
|
Eina_Future *future;
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
// Create a promise
|
|
|
|
promise = eina_promise_new(efl_loop_future_scheduler_get(loop),
|
|
|
|
_promise_cancel, NULL);
|
2017-12-13 04:23:39 -08:00
|
|
|
future = eina_future_new(promise);
|
2018-01-05 00:22:09 -08:00
|
|
|
printf("Test 3: Waiting for promise to be cancelled...\n");
|
2018-01-02 07:26:03 -08:00
|
|
|
|
|
|
|
// 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,
|
2018-01-04 11:28:26 -08:00
|
|
|
.data = loop);
|
2018-01-02 07:26:03 -08:00
|
|
|
|
|
|
|
// Cancel the future before it has a chance to resolve
|
2017-12-13 04:23:39 -08:00
|
|
|
eina_future_cancel(future);
|
2017-12-12 11:37:56 -08:00
|
|
|
}
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
/* ----------------------- Test 4 ---------------------- */
|
|
|
|
|
|
|
|
/* Resolve the passed promise to an integer with value 1 and cancel the timer */
|
2017-12-12 11:37:56 -08:00
|
|
|
static void
|
2018-01-02 07:26:03 -08:00
|
|
|
_test4_resolve(void *data, const Efl_Event *event)
|
2017-12-12 11:37:56 -08:00
|
|
|
{
|
2018-01-02 07:26:03 -08:00
|
|
|
Eina_Promise *promise = (Eina_Promise *)data;
|
2017-12-13 04:23:39 -08:00
|
|
|
|
|
|
|
eina_promise_resolve(promise, eina_value_int_init(1));
|
|
|
|
|
|
|
|
efl_del(event->object);
|
2017-12-12 11:37:56 -08:00
|
|
|
}
|
|
|
|
|
2017-12-13 04:23:39 -08:00
|
|
|
/*
|
|
|
|
* A value callback to chain, taking in an int value and returning to chain
|
|
|
|
* the int multiplied by two.
|
|
|
|
*/
|
2017-12-12 11:37:56 -08:00
|
|
|
static Eina_Value
|
2018-01-02 07:26:03 -08:00
|
|
|
_chain_multiply_cb(void *data EINA_UNUSED, const Eina_Value value,
|
2017-12-13 04:23:39 -08:00
|
|
|
const Eina_Future *dead_future EINA_UNUSED)
|
2017-12-12 11:37:56 -08:00
|
|
|
{
|
2018-01-02 07:26:03 -08:00
|
|
|
int i;
|
2017-12-12 11:37:56 -08:00
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
if (value.type != EINA_VALUE_TYPE_INT)
|
2017-12-13 04:23:39 -08:00
|
|
|
{
|
2018-01-02 07:26:03 -08:00
|
|
|
fprintf(stderr, "Expected type 'int', got '%s'\n", value.type->name);
|
|
|
|
return value;
|
2017-12-13 04:23:39 -08:00
|
|
|
}
|
2017-12-12 11:37:56 -08:00
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
eina_value_get(&value, &i);
|
|
|
|
return *eina_value_util_int_new(i * 2);
|
2017-12-12 11:37:56 -08:00
|
|
|
}
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
/* This chained callback exits the example */
|
2017-12-12 11:37:56 -08:00
|
|
|
static Eina_Value
|
2018-01-02 07:26:03 -08:00
|
|
|
_exit_cb(void *data EINA_UNUSED, const Eina_Value value EINA_UNUSED,
|
2017-12-13 04:23:39 -08:00
|
|
|
const Eina_Future *dead_future EINA_UNUSED)
|
2017-12-12 11:37:56 -08:00
|
|
|
{
|
|
|
|
efl_exit(0);
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
printf(" Test 4 finished\n");
|
|
|
|
|
2017-12-13 04:23:39 -08:00
|
|
|
return EINA_VALUE_EMPTY;
|
2017-12-12 11:37:56 -08:00
|
|
|
}
|
|
|
|
|
2017-12-13 04:23:39 -08:00
|
|
|
/*
|
2018-01-02 07:26:03 -08:00
|
|
|
* 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
|
2017-12-13 04:23:39 -08:00
|
|
|
* eina_future_cb_console prints a message including the value before passing
|
|
|
|
* it on.
|
|
|
|
*/
|
2017-12-12 11:37:56 -08:00
|
|
|
static void
|
2018-01-04 11:28:26 -08:00
|
|
|
_test4_chained_future(Efl_Loop *loop)
|
2017-12-13 04:23:39 -08:00
|
|
|
{
|
2018-01-02 07:26:03 -08:00
|
|
|
Eina_Promise *promise;
|
|
|
|
|
|
|
|
// Create a promise
|
|
|
|
promise = eina_promise_new(efl_loop_future_scheduler_get(loop),
|
|
|
|
_promise_cancel, NULL);
|
|
|
|
|
2018-01-05 00:22:09 -08:00
|
|
|
printf("Test 4: Waiting for promise to be resolved...\n");
|
2018-01-02 07:26:03 -08:00
|
|
|
// 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),
|
2017-12-13 04:23:39 -08:00
|
|
|
{.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),
|
2017-12-12 11:37:56 -08:00
|
|
|
{.cb = _exit_cb, .data = NULL});
|
2018-01-02 07:26:03 -08:00
|
|
|
|
|
|
|
// 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),
|
2019-03-09 06:54:38 -08:00
|
|
|
efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TIMER_TICK,
|
2018-01-02 07:26:03 -08:00
|
|
|
_test4_resolve, promise));
|
2017-12-12 11:37:56 -08:00
|
|
|
}
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
/* ----------------------- Main ---------------------- */
|
|
|
|
|
2017-12-12 11:37:56 -08:00
|
|
|
EAPI_MAIN void
|
2018-01-04 11:28:26 -08:00
|
|
|
efl_main(void *data EINA_UNUSED, const Efl_Event *ev)
|
2017-12-12 11:37:56 -08:00
|
|
|
{
|
2018-01-04 11:28:26 -08:00
|
|
|
Efl_Loop *loop = ev->object;
|
|
|
|
|
2018-01-02 07:26:03 -08:00
|
|
|
// Start the first test, the others will be launched when this one finishes
|
2018-01-04 11:28:26 -08:00
|
|
|
_test1_simple_future(loop);
|
2017-12-12 11:37:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EFL_MAIN()
|