remove elgacy ecore event usage in futures that limit to mainloop only

also eina_procmis was not threadsafe so cannto use loops in different
threads at all until this was made safe. needed to disable the old
ecore_event using code in for ecore futures and create a new efl loop
message future and handler instead ... but now a quick experiment with
multiple loops in 10 threads plus mainloop have timers at least work.
i need to test more like fd handlers etc etc. but it's a step.
This commit is contained in:
Carsten Haitzler 2017-12-28 01:19:52 +09:00
parent 6ccfea3d51
commit b27ca559f6
13 changed files with 300 additions and 47 deletions

View File

@ -38,6 +38,8 @@ ecore_eolian_files_public = \
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 \
@ -97,6 +99,8 @@ lib/ecore/efl_loop_fd.c \
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 \

View File

@ -32,6 +32,9 @@
#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
*

View File

@ -12,16 +12,16 @@ typedef struct _Ecore_Future_Schedule_Entry
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;
//
//////
@ -71,17 +71,6 @@ ecore_event_add(int type,
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)
{
@ -127,8 +116,11 @@ ecore_event_current_event_get(void)
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);
@ -139,7 +131,8 @@ ecore_future_dispatched(void *data EINA_UNUSED, int type EINA_UNUSED, void *eve
}
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)
@ -149,10 +142,35 @@ ecore_future_free(void *user_data, void *func_data EINA_UNUSED)
}
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));
@ -161,9 +179,19 @@ ecore_future_schedule(Eina_Future_Scheduler *sched, Eina_Future_Scheduler_Cb cb,
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:
@ -174,12 +202,17 @@ ecore_future_schedule(Eina_Future_Scheduler *sched, Eina_Future_Scheduler_Cb cb,
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 = {
@ -238,24 +271,28 @@ _ecore_event_init(void)
//////
// 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;
}
@ -266,9 +303,9 @@ _ecore_event_shutdown(void)
//////
// 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;
//
//////

View File

@ -84,6 +84,7 @@ typedef struct _Ecore_Factorized_Idle Ecore_Factorized_Idle;
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;
@ -103,11 +104,22 @@ struct _Message
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;

View File

@ -460,7 +460,10 @@ _efl_loop_timer_efl_object_parent_set(Eo *obj, Efl_Loop_Timer_Data *pd, Efl_Obje
_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;

View File

@ -307,6 +307,8 @@ _efl_loop_efl_object_constructor(Eo *obj, Efl_Loop_Data *pd)
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;
}
@ -315,6 +317,8 @@ _efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd)
{
_ecore_main_content_clear(pd);
pd->future_message_handler = NULL;
eina_hash_free(pd->providers);
pd->providers = NULL;
@ -325,8 +329,11 @@ _efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd)
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));
@ -439,10 +446,10 @@ ecore_loop_promise_unregister(Efl_Loop *l, Efl_Promise *p)
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
@ -479,6 +486,7 @@ _efl_loop_idle(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
{
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);
@ -486,8 +494,7 @@ _efl_loop_idle(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
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;
@ -504,8 +511,11 @@ static void
_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);
}
@ -520,11 +530,19 @@ _efl_loop_timeout_done(void *data, const Efl_Event *event)
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);
@ -533,11 +551,14 @@ _efl_loop_timeout(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, double tim)
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;
@ -699,7 +720,20 @@ efl_loop_future_scheduler_get(Eo *obj)
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));
}

View File

@ -7,6 +7,9 @@ class Efl.Loop.Message (Efl.Object)
specific message types.]]
methods {
}
events {
message: Efl.Loop.Message; [[The message payload data]]
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;

View File

@ -0,0 +1,49 @@
#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"

View File

@ -0,0 +1,21 @@
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;
}
}

View File

@ -0,0 +1,51 @@
#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"

View File

@ -0,0 +1,21 @@
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; [[ ]]
}
}

View File

@ -90,6 +90,8 @@ _efl_loop_message_handler_message_call(Eo *obj, Efl_Loop_Message_Handler_Data *p
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...

View File

@ -3,6 +3,7 @@
#endif
#include "eina_private.h"
#include "eina_lock.h"
#include "eina_promise.h"
#include "eina_mempool.h"
#include "eina_promise_private.h"
@ -117,6 +118,7 @@ struct _Eina_Future {
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;
@ -407,7 +409,9 @@ _eina_future_dispatch(Eina_Future *f, Eina_Value value)
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);
}
@ -436,7 +440,9 @@ _eina_future_cancel(Eina_Future *f, int err)
{
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)
@ -470,7 +476,9 @@ _eina_future_schedule(Eina_Promise *p,
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;
@ -523,6 +531,8 @@ eina_promise_init(void)
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:
@ -537,14 +547,17 @@ eina_promise_init(void)
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);