//GENERIC_ALLOC_FREE(Ecore_Poller, ecore_poller);
GENERIC_ALLOC_FREE(Ecore_Pipe, ecore_pipe);
GENERIC_ALLOC_FREE(Ecore_Fd_Handler, ecore_fd_handler);
+GENERIC_ALLOC_FREE(Efl_Loop_Promise_Simple_Data, efl_loop_promise_simple_data);
#ifdef _WIN32
GENERIC_ALLOC_FREE(Ecore_Win32_Handler, ecore_win32_handler);
#endif
// &ecore_poller_mp,
&ecore_pipe_mp,
&ecore_fd_handler_mp,
+ &efl_loop_promise_simple_data_mp,
#ifdef _WIN32
&ecore_win32_handler_mp
#endif
// MP_SIZE_INIT(Ecore_Poller, ecore_poller);
MP_SIZE_INIT(Ecore_Pipe, ecore_pipe);
MP_SIZE_INIT(Ecore_Fd_Handler, ecore_fd_handler);
+ MP_SIZE_INIT(Efl_Loop_Promise_Simple_Data, efl_loop_promise_simple_data);
#ifdef _WIN32
MP_SIZE_INIT(Ecore_Win32_Handler, ecore_win32_handler);
#endif
};
GENERIC_ALLOC_SIZE_DECLARE(Ecore_Fd_Handler);
+typedef struct _Efl_Loop_Promise_Simple_Data {
+ union {
+ Ecore_Timer *timer;
+ Ecore_Idler *idler;
+ };
+ Eina_Promise *promise;
+} Efl_Loop_Promise_Simple_Data;
+GENERIC_ALLOC_SIZE_DECLARE(Efl_Loop_Promise_Simple_Data);
+
#ifdef _WIN32
struct _Ecore_Win32_Handler
{
{ EFL_LOOP_TIMER_EVENT_TICK, _efl_loop_timeout_cb },
{ EFL_EVENT_DEL, _efl_loop_timeout_force_cancel_cb });
+static Eina_Future *
+_efl_loop_Eina_FutureXXX_job(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
+{
+ // NOTE: Eolian should do efl_future_then() to bind future to object.
+ return efl_future_Eina_FutureXXX_then(obj,
+ eina_future_resolved(efl_loop_future_scheduler_get(obj),
+ EINA_VALUE_EMPTY));
+}
+
+static void
+_efl_loop_Eina_FutureXXX_idle_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUSED)
+{
+ Efl_Loop_Promise_Simple_Data *d = data;
+ ecore_idler_del(d->idler);
+ efl_loop_promise_simple_data_mp_free(d);
+}
+
+static Eina_Bool
+_efl_loop_Eina_FutureXXX_idle_done(void *data)
+{
+ Efl_Loop_Promise_Simple_Data *d = data;
+ eina_promise_resolve(d->promise, EINA_VALUE_EMPTY);
+ efl_loop_promise_simple_data_mp_free(d);
+ return EINA_FALSE;
+}
+
+static Eina_Future *
+_efl_loop_Eina_FutureXXX_idle(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
+{
+ Efl_Loop_Promise_Simple_Data *d;
+ Eina_Promise *p;
+
+ d = efl_loop_promise_simple_data_calloc(1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
+
+ d->idler = ecore_idler_add(_efl_loop_Eina_FutureXXX_idle_done, d);
+ EINA_SAFETY_ON_NULL_GOTO(d->idler, idler_error);
+
+ p = eina_promise_new(efl_loop_future_scheduler_get(obj),
+ _efl_loop_Eina_FutureXXX_idle_cancel, d);
+ // d is dead if p is NULL
+ EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL);
+ d->promise = p;
+
+ // NOTE: Eolian should do efl_future_then() to bind future to object.
+ return efl_future_Eina_FutureXXX_then(obj, eina_future_new(p));
+
+ idler_error:
+ efl_loop_promise_simple_data_mp_free(d);
+ return NULL;
+}
+
+static void
+_efl_loop_Eina_FutureXXX_timeout_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUSED)
+{
+ Efl_Loop_Promise_Simple_Data *d = data;
+ ecore_timer_del(d->timer);
+ efl_loop_promise_simple_data_mp_free(d);
+}
+
+static Eina_Bool
+_efl_loop_Eina_FutureXXX_timeout_done(void *data)
+{
+ Efl_Loop_Promise_Simple_Data *d = data;
+ eina_promise_resolve(d->promise, EINA_VALUE_EMPTY);
+ efl_loop_promise_simple_data_mp_free(d);
+ return EINA_FALSE;
+}
+
+static Eina_Future *
+_efl_loop_Eina_FutureXXX_timeout(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, double time)
+{
+ Efl_Loop_Promise_Simple_Data *d;
+ Eina_Promise *p;
+
+ d = efl_loop_promise_simple_data_calloc(1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
+
+ d->timer = ecore_timer_add(time, _efl_loop_Eina_FutureXXX_timeout_done, d);
+ EINA_SAFETY_ON_NULL_GOTO(d->timer, timer_error);
+
+ p = eina_promise_new(efl_loop_future_scheduler_get(obj),
+ _efl_loop_Eina_FutureXXX_timeout_cancel, d);
+ // d is dead if p is NULL
+ EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL);
+ d->promise = p;
+
+ // NOTE: Eolian should do efl_future_then() to bind future to object.
+ return efl_future_Eina_FutureXXX_then(obj, eina_future_new(p));
+
+ timer_error:
+ efl_loop_promise_simple_data_mp_free(d);
+ return NULL;
+}
+
/* This event will be triggered when the main loop is destroyed and destroy its timers along */
static void _efl_loop_internal_cancel(Efl_Internal_Promise *p);
typedef struct _Ecore_Factorized_Idle Ecore_Factorized_Idle;
+typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data;
+
typedef struct _Efl_Loop_Data Efl_Loop_Data;
struct _Efl_Loop_Data
{
//GENERIC_ALLOC_FREE_HEADER(Ecore_Poller, ecore_poller);
GENERIC_ALLOC_FREE_HEADER(Ecore_Pipe, ecore_pipe);
GENERIC_ALLOC_FREE_HEADER(Ecore_Fd_Handler, ecore_fd_handler);
+GENERIC_ALLOC_FREE_HEADER(Efl_Loop_Promise_Simple_Data, efl_loop_promise_simple_data);
#ifdef _WIN32
GENERIC_ALLOC_FREE_HEADER(Ecore_Win32_Handler, ecore_win32_handler);
#endif
scheduler: ptr(Eina.Future.Scheduler); [[The scheduler.]]
}
}
+ Eina_FutureXXX_job {
+ [[A future promise that will be resolved from a clean main
+ loop context as soon as possible.
+
+ This has higher priority, for low priority use
+ @.Eina_FutureXXX_idle
+ ]]
+ return: own(ptr(Eina.Future)) /* TODO: future<void> */; [[The future handle.]]
+ }
+ Eina_FutureXXX_idle {
+ [[A future promise that will be resolved from a clean main
+ loop context as soon as the main loop is idle.
+
+ This is a low priority version of @.Eina_FutureXXX_job
+ ]]
+ return: own(ptr(Eina.Future)) /* TODO: future<void> */; [[The future handle.]]
+ }
+ Eina_FutureXXX_timeout {
+ [[A future promise that will be resolved from a clean main
+ loop context after $time seconds.]]
+ params {
+ @in time: double; [[The time from now in second that the main loop will wait before triggering it.]]
+ }
+ return: own(ptr(Eina.Future)) /* future<void> */; [[The future handle.]]
+ }
job {
[[Will execute that promise in the near future.]]
params {
return v;
}
+static Eina_Value
+_promise_empty_done(void *data, const Eina_Value value, const Eina_Future *dead_future EINA_UNUSED)
+{
+ Eina_Bool *pdone = data;
+
+ if (!value.type) *pdone = EINA_TRUE;
+
+ ecore_main_loop_quit();
+
+ return value;
+}
+
+START_TEST(efl_test_timeout)
+{
+ Eina_Future *f;
+ Eina_Bool done = EINA_FALSE;
+
+ fail_if(!ecore_init());
+ f = eina_future_then(efl_loop_Eina_FutureXXX_timeout(ecore_main_loop_get(), 0.0001),
+ _promise_empty_done, &done);
+ fail_if(!f);
+ ecore_main_loop_begin();
+ ecore_shutdown();
+
+ fail_unless(done);
+}
+END_TEST
+
+START_TEST(efl_test_job)
+{
+ Eina_Future *f;
+ Eina_Bool done = EINA_FALSE;
+
+ fail_if(!ecore_init());
+ f = eina_future_then(efl_loop_Eina_FutureXXX_job(ecore_main_loop_get()),
+ _promise_empty_done, &done);
+ fail_if(!f);
+ ecore_main_loop_begin();
+ ecore_shutdown();
+
+ fail_unless(done);
+}
+END_TEST
+
+START_TEST(efl_test_idle)
+{
+ Eina_Future *f;
+ Eina_Bool done = EINA_FALSE;
+
+ fail_if(!ecore_init());
+ f = eina_future_then(efl_loop_Eina_FutureXXX_idle(ecore_main_loop_get()),
+ _promise_empty_done, &done);
+ fail_if(!f);
+ ecore_main_loop_begin();
+ ecore_shutdown();
+
+ fail_unless(done);
+}
+END_TEST
+
+
START_TEST(efl_test_promise_future_success)
{
Eina_Future *f;
void ecore_test_ecore_promise2(TCase *tc)
{
+ tcase_add_test(tc, efl_test_timeout);
+ tcase_add_test(tc, efl_test_job);
+ tcase_add_test(tc, efl_test_idle);
tcase_add_test(tc, efl_test_promise_future_success);
tcase_add_test(tc, efl_test_promise_future_failure);
tcase_add_test(tc, efl_test_promise_future_chain_no_error);