ecore_eolian_files = \
$(ecore_eolian_files_public) \
+ lib/ecore/efl_loop_message_future_handler.eo \
+ lib/ecore/efl_loop_message_future.eo \
lib/ecore/efl_promise.eo \
lib/ecore/efl_model_item.eo \
lib/ecore/efl_model_container.eo \
lib/ecore/efl_loop_handler.c \
lib/ecore/efl_loop_message.c \
lib/ecore/efl_loop_message_handler.c \
+lib/ecore/efl_loop_message_future.c \
+lib/ecore/efl_loop_message_future_handler.c \
lib/ecore/efl_io_closer_fd.c \
lib/ecore/efl_io_positioner_fd.c \
lib/ecore/efl_io_reader_fd.c \
#include "ecore_event_message.eo.h"
#include "ecore_event_message_handler.eo.h"
+#include "efl_loop_message_future.eo.h"
+#include "efl_loop_message_future_handler.eo.h"
+
/**
* @ingroup Ecore_MainLoop_Group
*
Eina_Future_Schedule_Entry base;
Eina_Future_Scheduler_Cb cb;
Eina_Future *future;
- Ecore_Event *event;
+ Eo *event;
Eina_Value value;
} Ecore_Future_Schedule_Entry;
//////
// XXX: still using legacy ecore events
-static Ecore_Event_Handler *future_handler = NULL;
+//static Ecore_Event_Handler *future_handler = NULL;
static Eina_Bool shutting_down = EINA_FALSE;
static Eina_Mempool *mp_future_schedule_entry = NULL;
-static int ECORE_EV_FUTURE_ID = -1;
+//static int ECORE_EV_FUTURE_ID = -1;
//
//////
return (Ecore_Event *)msg;
}
-static void
-_event_del_cb(void *data, const Efl_Event *ev)
-{
- Ecore_Future_Schedule_Entry *entry = data;
- if ((ev->object == (Eo *) entry->event) && entry->future)
- {
- eina_future_cancel(entry->future);
- eina_value_flush(&entry->value);
- }
-}
-
EAPI void *
ecore_event_del(Ecore_Event *event)
{
return ecore_event_message_handler_current_event_get(_event_msg_handler);
}
+/* XXX:
static Eina_Bool
-ecore_future_dispatched(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+ecore_future_dispatched(void *data EINA_UNUSED,
+ int type EINA_UNUSED,
+ void *event)
{
Ecore_Future_Schedule_Entry *entry = event;
EINA_SAFETY_ON_NULL_RETURN_VAL(entry, EINA_FALSE);
}
static void
-ecore_future_free(void *user_data, void *func_data EINA_UNUSED)
+ecore_future_free(void *user_data,
+ void *func_data EINA_UNUSED)
{
Ecore_Future_Schedule_Entry *entry = user_data;
if (entry->event)
}
eina_mempool_free(mp_future_schedule_entry, entry);
}
+*/
+
+static void
+_future_dispatch_cb(void *data, const Efl_Event *ev EINA_UNUSED)
+{
+ Ecore_Future_Schedule_Entry *entry = data;
+ entry->event = NULL;
+ entry->cb(entry->future, entry->value);
+}
+
+static void
+_event_del_cb(void *data, const Efl_Event *ev)
+{
+ Ecore_Future_Schedule_Entry *entry = data;
+ if ((ev->object == (Eo *) entry->event) && entry->future)
+ {
+ eina_future_cancel(entry->future);
+ eina_value_flush(&entry->value);
+ }
+ eina_mempool_free(mp_future_schedule_entry, entry);
+}
static Eina_Future_Schedule_Entry *
-ecore_future_schedule(Eina_Future_Scheduler *sched, Eina_Future_Scheduler_Cb cb, Eina_Future *future, Eina_Value value)
+ecore_future_schedule(Eina_Future_Scheduler *sched,
+ Eina_Future_Scheduler_Cb cb,
+ Eina_Future *future,
+ Eina_Value value)
{
+ Efl_Loop_Future_Scheduler *loopsched = (Efl_Loop_Future_Scheduler *)sched;
Ecore_Future_Schedule_Entry *entry;
entry = eina_mempool_malloc(mp_future_schedule_entry, sizeof(*entry));
entry->cb = cb;
entry->future = future;
entry->value = value;
- entry->event = ecore_event_add(ECORE_EV_FUTURE_ID, entry, ecore_future_free, entry);
+ entry->event = efl_loop_message_future_handler_message_type_add
+ (loopsched->loop_data->future_message_handler);
EINA_SAFETY_ON_NULL_GOTO(entry->event, err);
- efl_event_callback_add((Eo *) entry->event, EFL_EVENT_DEL, _event_del_cb, entry);
+ efl_loop_message_future_data_set(entry->event, entry);
+ efl_loop_message_handler_message_send
+ (loopsched->loop_data->future_message_handler, entry->event);
+// XXX:
+// entry->event = ecore_event_add(ECORE_EV_FUTURE_ID, entry,
+// ecore_future_free, entry);
+ efl_event_callback_add((Eo *)entry->event, EFL_LOOP_MESSAGE_EVENT_MESSAGE,
+ _future_dispatch_cb, entry);
+ efl_event_callback_add((Eo *)entry->event, EFL_EVENT_DEL,
+ _event_del_cb, entry);
return &entry->base;
err:
static void
ecore_future_recall(Eina_Future_Schedule_Entry *s_entry)
{
+ Eo *msg;
+
if (shutting_down) return;
Ecore_Future_Schedule_Entry *entry = (Ecore_Future_Schedule_Entry *)s_entry;
EINA_SAFETY_ON_NULL_RETURN(entry->event);
- ecore_event_del(entry->event);
+// XXX:
+// ecore_event_del(entry->event);
+ msg = entry->event;
eina_value_flush(&entry->value);
entry->event = NULL;
+ efl_del(msg);
}
static Eina_Future_Scheduler ecore_future_scheduler = {
//////
// XXX: ecore future still using legacy...
shutting_down = EINA_FALSE;
- ECORE_EV_FUTURE_ID = ecore_event_type_new();
- future_handler = ecore_event_handler_add(ECORE_EV_FUTURE_ID, ecore_future_dispatched, NULL);
- EINA_SAFETY_ON_NULL_GOTO(future_handler, err_handler);
+// ECORE_EV_FUTURE_ID = ecore_event_type_new();
+// future_handler = ecore_event_handler_add(ECORE_EV_FUTURE_ID, ecore_future_dispatched, NULL);
+// EINA_SAFETY_ON_NULL_GOTO(future_handler, err_handler);
//FIXME: Is 512 too high?
- mp_future_schedule_entry = eina_mempool_add(choice, "Ecore_Future_Event",
- NULL, sizeof(Ecore_Future_Schedule_Entry),
- 512);
- EINA_SAFETY_ON_NULL_GOTO(mp_future_schedule_entry, err_pool);
+ if (!mp_future_schedule_entry)
+ {
+ mp_future_schedule_entry = eina_mempool_add
+ (choice, "Ecore_Future_Event", NULL,
+ sizeof(Ecore_Future_Schedule_Entry), 512);
+ EINA_SAFETY_ON_NULL_GOTO(mp_future_schedule_entry, err_pool);
+ }
//
//////
return EINA_TRUE;
err_pool:
- ecore_event_handler_del(future_handler);
- future_handler = NULL;
- err_handler:
- ECORE_EV_FUTURE_ID = -1;
+// XXX:
+// ecore_event_handler_del(future_handler);
+// future_handler = NULL;
+// err_handler:
+// ECORE_EV_FUTURE_ID = -1;
return EINA_FALSE;
}
//////
// XXX: ecore future still using legacy...
- ecore_event_handler_del(future_handler);
- future_handler = NULL;
- ECORE_EV_FUTURE_ID = -1;
+// ecore_event_handler_del(future_handler);
+// future_handler = NULL;
+// ECORE_EV_FUTURE_ID = -1;
//
//////
typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data;
typedef struct _Efl_Loop_Timer_Data Efl_Loop_Timer_Data;
+typedef struct _Efl_Loop_Future_Scheduler Efl_Loop_Future_Scheduler;
typedef struct _Efl_Loop_Data Efl_Loop_Data;
typedef struct _Message_Handler Message_Handler;
Eina_Bool delete_me;
};
+struct _Efl_Loop_Future_Scheduler
+{
+ Eina_Future_Scheduler eina_future_scheduler;
+ Eo *loop;
+ Efl_Loop_Data *loop_data;
+};
+
struct _Efl_Loop_Data
{
double loop_time;
Eina_Hash *providers;
+ Efl_Loop_Future_Scheduler future_scheduler;
+
+ Efl_Loop_Message_Handler *future_message_handler;
+
Efl_Loop_Timer *poll_high;
Efl_Loop_Timer *poll_medium;
Efl_Loop_Timer *poll_low;
_efl_loop_timer_util_loop_clear(pd);
pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS);
- pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS);
+ if (pd->loop)
+ pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS);
+ else
+ pd->loop_data = NULL;
if (efl_parent_get(obj) != parent) return;
pd->message_handlers = eina_inarray_new(sizeof(Message_Handler), 32);
pd->epoll_fd = -1;
pd->timer_fd = -1;
+ pd->future_message_handler = efl_loop_message_handler_get
+ (EFL_LOOP_CLASS, obj, EFL_LOOP_MESSAGE_FUTURE_HANDLER_CLASS);
return obj;
}
{
_ecore_main_content_clear(pd);
+ pd->future_message_handler = NULL;
+
eina_hash_free(pd->providers);
pd->providers = NULL;
efl_del(pd->poll_high);
pd->poll_high = NULL;
- eina_inarray_free(pd->message_handlers);
- pd->message_handlers = NULL;
+ if (pd->message_handlers)
+ {
+ eina_inarray_free(pd->message_handlers);
+ pd->message_handlers = NULL;
+ }
efl_destructor(efl_super(obj, EFL_LOOP_CLASS));
static Eina_Future *
_efl_loop_job(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
{
+ Eina_Future_Scheduler *sched = efl_loop_future_scheduler_get(obj);
// 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));
+ (obj, eina_future_resolved(sched, EINA_VALUE_EMPTY));
}
EOLIAN static void
{
Efl_Loop_Promise_Simple_Data *d;
Eina_Promise *p;
+ Eina_Future_Scheduler *sched = efl_loop_future_scheduler_get(obj);
d = efl_loop_promise_simple_data_calloc(1);
EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
d->idler = ecore_idler_add(_efl_loop_idle_done, d);
EINA_SAFETY_ON_NULL_GOTO(d->idler, idler_error);
- p = eina_promise_new(efl_loop_future_scheduler_get(obj),
- _efl_loop_idle_cancel, d);
+ p = eina_promise_new(sched, _efl_loop_idle_cancel, d);
// d is dead if p is NULL
EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL);
d->promise = p;
_efl_loop_timeout_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUSED)
{
Efl_Loop_Promise_Simple_Data *d = data;
- efl_del(d->timer);
- d->timer = NULL;
+ if (d->timer)
+ {
+ efl_del(d->timer);
+ d->timer = NULL;
+ }
efl_loop_promise_simple_data_mp_free(d);
}
efl_del(event->object);
}
+static void
+_efl_loop_timeout_del(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Efl_Loop_Promise_Simple_Data *d = data;
+ d->timer = NULL;
+}
+
static Eina_Future *
_efl_loop_timeout(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, double tim)
{
Efl_Loop_Promise_Simple_Data *d;
Eina_Promise *p;
+ Eina_Future_Scheduler *sched = efl_loop_future_scheduler_get(obj);
d = efl_loop_promise_simple_data_calloc(1);
EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
efl_loop_timer_interval_set(efl_added, tim),
efl_event_callback_add(efl_added,
EFL_LOOP_TIMER_EVENT_TICK,
- _efl_loop_timeout_done, d));
+ _efl_loop_timeout_done, d),
+ efl_event_callback_add(efl_added,
+ EFL_EVENT_DEL,
+ _efl_loop_timeout_del, d)
+ );
EINA_SAFETY_ON_NULL_GOTO(d->timer, timer_error);
- p = eina_promise_new(efl_loop_future_scheduler_get(obj),
- _efl_loop_timeout_cancel, d);
+ p = eina_promise_new(sched, _efl_loop_timeout_cancel, d);
// d is dead if p is NULL
EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL);
d->promise = p;
if (!obj) return NULL;
if (efl_isa(obj, EFL_LOOP_CLASS))
- return _ecore_event_future_scheduler_get();
+ {
+ Efl_Loop_Data *pd = efl_data_scope_get(obj, EFL_LOOP_CLASS);
+
+ if (!pd) return NULL;
+ if (!pd->future_scheduler.loop)
+ {
+ Eina_Future_Scheduler *sched =
+ _ecore_event_future_scheduler_get();
+ pd->future_scheduler.eina_future_scheduler = *sched;
+ pd->future_scheduler.loop = obj;
+ pd->future_scheduler.loop_data = pd;
+ }
+ return &(pd->future_scheduler.eina_future_scheduler);
+ }
return efl_loop_future_scheduler_get(efl_loop_get(obj));
}
specific message types.]]
methods {
}
+ events {
+ message: Efl.Loop.Message; [[The message payload data]]
+ }
implements {
Efl.Object.constructor;
Efl.Object.destructor;
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Ecore.h>
+
+#include "ecore_private.h"
+
+#define MY_CLASS EFL_LOOP_MESSAGE_FUTURE_CLASS
+
+//////////////////////////////////////////////////////////////////////////
+
+typedef struct _Efl_Loop_Message_Future_Data Efl_Loop_Message_Future_Data;
+
+struct _Efl_Loop_Message_Future_Data
+{
+ void *data;
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+EOLIAN static void
+_efl_loop_message_future_data_set(Eo *obj EINA_UNUSED, Efl_Loop_Message_Future_Data *pd, void *data)
+{
+ pd->data = data;
+}
+
+EOLIAN static void *
+_efl_loop_message_future_data_get(Eo *obj EINA_UNUSED, Efl_Loop_Message_Future_Data *pd)
+{
+ return pd->data;
+}
+
+EOLIAN static Efl_Object *
+_efl_loop_message_future_efl_object_constructor(Eo *obj, Efl_Loop_Message_Future_Data *pd EINA_UNUSED)
+{
+ obj = efl_constructor(efl_super(obj, MY_CLASS));
+ return obj;
+}
+
+EOLIAN static void
+_efl_loop_message_future_efl_object_destructor(Eo *obj, Efl_Loop_Message_Future_Data *pd EINA_UNUSED)
+{
+ efl_destructor(efl_super(obj, MY_CLASS));
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+#include "efl_loop_message_future.eo.c"
--- /dev/null
+import efl_types;
+import eina_types;
+
+class Efl.Loop.Message.Future (Efl.Loop.Message)
+{
+ [[ Used internally for futures on the loop ]]
+ methods {
+ @property data {
+ [[ ]]
+ set { }
+ get { }
+ values {
+ data: void_ptr; [[ ]]
+ }
+ }
+ }
+ implements {
+ Efl.Object.constructor;
+ Efl.Object.destructor;
+ }
+}
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Ecore.h>
+
+#include "ecore_private.h"
+
+#define MY_CLASS EFL_LOOP_MESSAGE_FUTURE_HANDLER_CLASS
+
+typedef struct _Efl_Loop_Message_Future_Handler_Data Efl_Loop_Message_Future_Handler_Data;
+
+struct _Efl_Loop_Message_Future_Handler_Data
+{
+ void *data; // dummy;
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+EOLIAN static Efl_Loop_Message_Future *
+_efl_loop_message_future_handler_message_type_add(Eo *obj, Efl_Loop_Message_Future_Handler_Data *pd)
+{
+ // XXX: implemented event obj cache
+ return efl_add(EFL_LOOP_MESSAGE_FUTURE_CLASS, obj);
+}
+
+EOLIAN static Efl_Object *
+_efl_loop_message_future_handler_efl_object_constructor(Eo *obj, Efl_Loop_Message_Future_Handler_Data *pd EINA_UNUSED)
+{
+ obj = efl_constructor(efl_super(obj, MY_CLASS));
+ return obj;
+}
+
+EOLIAN static void
+_efl_loop_message_future_handler_efl_object_destructor(Eo *obj, Efl_Loop_Message_Future_Handler_Data *pd EINA_UNUSED)
+{
+ efl_destructor(efl_super(obj, MY_CLASS));
+}
+
+EOLIAN static void
+_efl_loop_message_future_handler_efl_loop_message_handler_message_call(Eo *obj, Efl_Loop_Message_Future_Handler_Data *pd EINA_UNUSED, Efl_Loop_Message *message)
+{
+ efl_event_callback_call
+ (obj, EFL_LOOP_MESSAGE_FUTURE_HANDLER_EVENT_MESSAGE_FUTURE, message);
+ efl_loop_message_handler_message_call
+ (efl_super(obj, MY_CLASS), message);
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+#include "efl_loop_message_future_handler.eo.c"
--- /dev/null
+import efl_types;
+import eina_types;
+
+class Efl.Loop.Message.Future.Handler (Efl.Loop.Message.Handler)
+{
+ [[ Internal use for future on an efl loop - replacing legacy ecore events ]]
+ methods {
+ message_type_add {
+ [[ ]]
+ return: Efl.Loop.Message.Future; [[ ]]
+ }
+ }
+ events {
+ message,future: Efl.Loop.Message.Future; [[ ]]
+ }
+ implements {
+ Efl.Object.constructor;
+ Efl.Object.destructor;
+ Efl.Loop.Message.Handler.message_call; [[ ]]
+ }
+}
msg->delete_me = EINA_TRUE;
break;
}
+ efl_event_callback_call(message, EFL_LOOP_MESSAGE_EVENT_MESSAGE,
+ message);
efl_event_callback_call(obj, EFL_LOOP_MESSAGE_HANDLER_EVENT_MESSAGE,
message);
// XXX: implement message object cache...
#endif
#include "eina_private.h"
+#include "eina_lock.h"
#include "eina_promise.h"
#include "eina_mempool.h"
#include "eina_promise_private.h"
static Eina_Mempool *_promise_mp = NULL;
static Eina_Mempool *_future_mp = NULL;
+static Eina_Lock _pending_futures_lock;
static Eina_List *_pending_futures = NULL;
static int _promise_log_dom = -1;
static void
_scheduled_entry_cb(Eina_Future *f, Eina_Value value)
{
+ eina_lock_take(&_pending_futures_lock);
_pending_futures = eina_list_remove(_pending_futures, f);
+ eina_lock_release(&_pending_futures_lock);
f->scheduled_entry = NULL;
_eina_future_dispatch(f, value);
}
{
eina_future_schedule_entry_recall(f->scheduled_entry);
f->scheduled_entry = NULL;
+ eina_lock_take(&_pending_futures_lock);
_pending_futures = eina_list_remove(_pending_futures, f);
+ eina_lock_release(&_pending_futures_lock);
}
if (f->promise)
f, value);
EINA_SAFETY_ON_NULL_GOTO(f->scheduled_entry, err);
assert(f->scheduled_entry->scheduler != NULL);
+ eina_lock_take(&_pending_futures_lock);
_pending_futures = eina_list_append(_pending_futures, f);
+ eina_lock_release(&_pending_futures_lock);
DBG("The promise %p schedule the future %p with cb: %p and data: %p",
p, f, f->cb, f->data);
return;
NULL, sizeof(Eina_Future), 512);
EINA_SAFETY_ON_NULL_GOTO(_future_mp, err_future);
+ eina_lock_recursive_new(&_pending_futures_lock);
+
return EINA_TRUE;
err_future:
EAPI void
__eina_promise_cancel_all(void)
{
+ eina_lock_take(&_pending_futures_lock);
while (_pending_futures)
_eina_future_cancel(_pending_futures->data, ECANCELED);
+ eina_lock_release(&_pending_futures_lock);
}
Eina_Bool
eina_promise_shutdown(void)
{
__eina_promise_cancel_all();
+ eina_lock_free(&_pending_futures_lock);
eina_mempool_del(_future_mp);
eina_mempool_del(_promise_mp);
eina_log_domain_unregister(_promise_log_dom);