ecore - begin moving data into the efl loop data in the object

we really should have data inside the loop object, so begin moving it
one small thing at a time. this is the basics that will allow multiple
efl loops. make an eo efl object and class for fd handlers that is efl loop
bound make fd handlers really bound to their parent loop and not global  as
well as have a nice class/obj. create an message queue per loop and
put legacy ecore events on top of it... and a lot more.

this is not 100% done, but it's a lot of the core and groundwork.
various ecore_timer_add(), ecore_diler_add() etc. need changes.

The following still need doing:

  ecore_timer (internal usage for sure)
  ecore_idler (internal usage for sure)
  ecore_idle_enterer
  ecore_idle_exiter
  ecore_pollers? (is the new efl loop stuff ok?)
  ecore_exe (fork/spawn from any thread and track exe from that thread?)
  ecore_signal code
  ecore_throttle (should we have a single global too? we have per loop)
  ecore_app ? (should every loop be given its own argv/argc?)

Lots of internal ecore code uses/calls these legacy calls and we
should have efl loop replacements and/or use the ones we have

The following will bedifferently designed for loop to loop
control/messaging/ipc:

  ecore_thread
  ecore_pipe
This commit is contained in:
Carsten Haitzler 2017-11-09 15:59:04 +09:00
parent ccfa9ae220
commit 5dd52fd09b
32 changed files with 5071 additions and 3981 deletions

View File

@ -3,12 +3,17 @@
ecore_eolian_files_legacy = \
lib/ecore/ecore_exe.eo \
lib/ecore/ecore_event_message.eo \
lib/ecore/ecore_event_message_handler.eo \
lib/ecore/efl_loop_timer.eo
ecore_eolian_files_public = \
lib/ecore/efl_loop.eo \
lib/ecore/efl_loop_consumer.eo \
lib/ecore/efl_loop_fd.eo \
lib/ecore/efl_loop_handler.eo \
lib/ecore/efl_loop_message.eo \
lib/ecore/efl_loop_message_handler.eo \
lib/ecore/efl_io_closer_fd.eo \
lib/ecore/efl_io_positioner_fd.eo \
lib/ecore/efl_io_reader_fd.eo \
@ -84,8 +89,14 @@ lib/ecore/ecore_idle_exiter.c \
lib/ecore/ecore_idler.c \
lib/ecore/ecore_job.c \
lib/ecore/ecore_main.c \
lib/ecore/ecore_event_message.c \
lib/ecore/ecore_event_message_handler.c \
lib/ecore/efl_loop.c \
lib/ecore/efl_loop_consumer.c \
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_io_closer_fd.c \
lib/ecore/efl_io_positioner_fd.c \
lib/ecore/efl_io_reader_fd.c \
@ -115,6 +126,7 @@ lib/ecore/efl_interpolator_divisor.c \
lib/ecore/efl_interpolator_bounce.c \
lib/ecore/efl_interpolator_spring.c \
lib/ecore/efl_interpolator_cubic_bezier.c \
lib/ecore/ecore_main_timechanges.c \
lib/ecore/ecore_pipe.c \
lib/ecore/ecore_poller.c \
lib/ecore/ecore_time.c \
@ -124,7 +136,9 @@ lib/ecore/ecore_throttle.c \
lib/ecore/ecore_exe.c \
lib/ecore/ecore_exe_private.h \
lib/ecore/ecore_private.h \
lib/ecore/ecore_internal.h
lib/ecore/ecore_internal.h \
lib/ecore/ecore_main_common.h
if HAVE_WIN32
lib_ecore_libecore_la_SOURCES += lib/ecore/ecore_exe_win32.c

View File

@ -29,12 +29,18 @@
*/
#include "ecore_event_message.eo.h"
#include "ecore_event_message_handler.eo.h"
/**
* @ingroup Ecore_MainLoop_Group
*
* @{
*/
#include "efl_loop_message.eo.h"
#include "efl_loop_message_handler.eo.h"
#include "efl_loop.eo.h"
/**
@ -56,6 +62,7 @@ EAPI int efl_loop_exit_code_process(Eina_Value *value);
EAPI Eina_Future_Scheduler *efl_loop_future_scheduler_get(Eo *obj);
#include "efl_loop_fd.eo.h"
#include "efl_loop_handler.eo.h"
#include "efl_promise.eo.h"

View File

@ -273,14 +273,12 @@ ecore_init(void)
if (getenv("ECORE_FPS_DEBUG")) _ecore_fps_debug = 1;
if (_ecore_fps_debug) _ecore_fps_debug_init();
if (!ecore_mempool_init()) goto shutdown_mempool;
if (!_ecore_event_init()) goto shutdown_mempool;
_ecore_main_loop_init();
if (!_ecore_event_init()) goto shutdown_event;
vpath = efl_add(EFL_VPATH_CORE_CLASS, NULL);
if (vpath) efl_vpath_manager_register(EFL_VPATH_MANAGER_CLASS, 0, vpath);
_mainloop_singleton = efl_add(EFL_LOOP_CLASS, NULL);
_ecore_signal_init();
#ifndef HAVE_EXOTIC
_ecore_exe_init();
@ -359,6 +357,9 @@ ecore_init(void)
return _ecore_init_count;
shutdown_event:
_ecore_event_shutdown();
_ecore_main_shutdown();
shutdown_mempool:
ecore_mempool_shutdown();
efl_object_shutdown();
@ -403,9 +404,6 @@ ecore_shutdown(void)
}
#endif
efl_del(_mainloop_singleton);
_mainloop_singleton = NULL;
if (_ecore_fps_debug) _ecore_fps_debug_shutdown();
_ecore_poller_shutdown();
_ecore_animator_shutdown();
@ -442,7 +440,6 @@ ecore_shutdown(void)
#ifndef HAVE_EXOTIC
_ecore_exe_shutdown();
#endif
_efl_loop_timer_shutdown();
_ecore_event_shutdown();
_ecore_main_shutdown();
_ecore_signal_shutdown();

View File

@ -33,9 +33,9 @@ struct _Ecore_Mempool
}
//GENERIC_ALLOC_FREE(Ecore_Animator, ecore_animator);
GENERIC_ALLOC_FREE(Ecore_Event_Handler, ecore_event_handler);
GENERIC_ALLOC_FREE(Ecore_Event_Filter, ecore_event_filter);
GENERIC_ALLOC_FREE(Ecore_Event, ecore_event);
//GENERIC_ALLOC_FREE(Ecore_Event_Handler, ecore_event_handler);
//GENERIC_ALLOC_FREE(Ecore_Event_Filter, ecore_event_filter);
//GENERIC_ALLOC_FREE(Ecore_Event, ecore_event);
//GENERIC_ALLOC_FREE(Ecore_Idle_Exiter, ecore_idle_exiter);
//GENERIC_ALLOC_FREE(Ecore_Idle_Enterer, ecore_idle_enterer);
//GENERIC_ALLOC_FREE(Ecore_Idler, ecore_idler);
@ -51,9 +51,9 @@ GENERIC_ALLOC_FREE(Ecore_Win32_Handler, ecore_win32_handler);
static Ecore_Mempool *mempool_array[] = {
// &ecore_animator_mp,
&ecore_event_handler_mp,
&ecore_event_filter_mp,
&ecore_event_mp,
// &ecore_event_handler_mp,
// &ecore_event_filter_mp,
// &ecore_event_mp,
// &ecore_idle_exiter_mp,
// &ecore_idle_enterer_mp,
// &ecore_idler_mp,
@ -78,9 +78,9 @@ ecore_mempool_init(void)
Type##_mp.size = _ecore_sizeof_##TYPE
// MP_SIZE_INIT(Ecore_Animator, ecore_animator);
MP_SIZE_INIT(Ecore_Event_Handler, ecore_event_handler);
MP_SIZE_INIT(Ecore_Event_Filter, ecore_event_filter);
MP_SIZE_INIT(Ecore_Event, ecore_event);
// MP_SIZE_INIT(Ecore_Event_Handler, ecore_event_handler);
// MP_SIZE_INIT(Ecore_Event_Filter, ecore_event_filter);
// MP_SIZE_INIT(Ecore_Event, ecore_event);
// MP_SIZE_INIT(Ecore_Idle_Exiter, ecore_idle_exiter);
// MP_SIZE_INIT(Ecore_Idle_Enterer, ecore_idle_enterer);
// MP_SIZE_INIT(Ecore_Idler, ecore_idler);

View File

@ -0,0 +1,81 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Ecore.h>
#include "ecore_private.h"
#define MY_CLASS ECORE_EVENT_MESSAGE_CLASS
//////////////////////////////////////////////////////////////////////////
typedef struct _Ecore_Event_Message_Data Ecore_Event_Message_Data;
struct _Ecore_Event_Message_Data
{
int type;
void *ev;
Ecore_End_Cb free_func;
void *data;
};
//////////////////////////////////////////////////////////////////////////
EOLIAN static void
_ecore_event_message_data_set(Eo *obj EINA_UNUSED, Ecore_Event_Message_Data *pd, int type, void *data, void *free_func, void *free_data)
{
pd->type = type;
pd->ev = data;
pd->free_func = free_func;
pd->data = free_data;
}
EOLIAN static void
_ecore_event_message_data_get(Eo *obj EINA_UNUSED, Ecore_Event_Message_Data *pd, int *type, void **data, void **free_func, void **free_data)
{
if (type) *type = pd->type;
if (data) *data = pd->ev;
if (free_func) *free_func = pd->free_func;
if (free_data) *free_data = pd->data;
}
EOLIAN static void
_ecore_event_message_data_steal(Eo *obj EINA_UNUSED, Ecore_Event_Message_Data *pd, int *type, void **data, void **free_func, void **free_data)
{
if (type) *type = pd->type;
if (data) *data = pd->ev;
if (free_func) *free_func = pd->free_func;
if (free_data) *free_data = pd->data;
pd->type = -1;
pd->ev = NULL;
pd->free_func = NULL;
pd->data = NULL;
}
EOLIAN static Efl_Object *
_ecore_event_message_efl_object_constructor(Eo *obj, Ecore_Event_Message_Data *pd EINA_UNUSED)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
pd->type = -1;
return obj;
}
EOLIAN static void
_ecore_event_message_efl_object_destructor(Eo *obj EINA_UNUSED, Ecore_Event_Message_Data *pd EINA_UNUSED)
{
if (pd->ev)
{
Ecore_End_Cb fn_free = pd->free_func;
void *ev = pd->ev;
pd->ev = NULL;
if (fn_free) fn_free(pd->data, ev);
else free(ev);
}
efl_destructor(efl_super(obj, MY_CLASS));
}
//////////////////////////////////////////////////////////////////////////
#include "ecore_event_message.eo.c"

View File

@ -0,0 +1,34 @@
import efl_types;
import eina_types;
class Ecore.Event.Message (Efl.Loop.Message)
{
[[ For Legacy API usage Only. Legacy Ecore Events ]]
methods {
@property data {
[[ Property of the legacy event - set and get it ]]
set { }
get { }
values {
type: int; [[ The event type ]]
data: void_ptr; [[ The event data ]]
free_func: void_ptr; [[ Being lazy for legacy ]]
free_data: void_ptr; [[ Free func data ]]
}
}
data_steal {
[[ Steal the data out and set internal values to -1
for type and NULL for other vals ]]
params {
@out type: int; [[ The event type ]]
@out data: void_ptr; [[ The event data ]]
@out free_func: void_ptr; [[ Being lazy for legacy ]]
@out free_data: void_ptr; [[ Free func data ]]
}
}
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
}
}

View File

@ -0,0 +1,414 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Ecore.h>
#include "ecore_private.h"
#define MY_CLASS ECORE_EVENT_MESSAGE_HANDLER_CLASS
//////////////////////////////////////////////////////////////////////////
typedef struct _Handler Handler;
typedef struct _Filter Filter;
struct _Handler
{
EINA_INLIST;
Ecore_Event_Handler_Cb func;
void *data;
int type;
Eina_Bool delete_me : 1;
Eina_Bool to_add : 1;
};
struct _Filter
{
EINA_INLIST;
Ecore_Data_Cb func_start;
Ecore_Filter_Cb func_filter;
Ecore_End_Cb func_end;
void *data;
void *loop_data;
Eina_Bool delete_me : 1;
};
typedef struct _Ecore_Event_Message_Handler_Data Ecore_Event_Message_Handler_Data;
struct _Ecore_Event_Message_Handler_Data
{
int event_type_count;
Eina_Inlist **handlers; // array of event_type_count inlists of handlers
Eina_Inlist *filters;
Eina_List *handlers_delete;
Eina_List *handlers_add;
Eina_List *filters_delete;
Eina_List *filters_add;
void *current_event_data;
int current_event_type;
int handlers_walking;
int filters_walking;
};
//////////////////////////////////////////////////////////////////////////
Eina_Bool
_ecore_event_do_filter(void *handler_pd, Eo *msg_handler, Eo *msg)
{
Filter *f;
void *ev;
int type;
Ecore_Event_Message_Handler_Data *eemhd = handler_pd;
if (!eemhd->filters) return EINA_TRUE;
if (!efl_isa(msg_handler, MY_CLASS)) return EINA_TRUE;
eemhd->filters_walking++;
EINA_INLIST_FOREACH(eemhd->filters, f)
{
if (f->delete_me) continue;
type = -1;
ev = NULL;
ecore_event_message_data_get(msg, &type, &ev, NULL, NULL);
if (type >= 0)
{
if (!f->func_filter(f->data, f->loop_data, type, ev))
_efl_loop_message_unsend(msg);
}
}
eemhd->filters_walking--;
return EINA_TRUE;
}
void
_ecore_event_filters_call(Eo *obj, Efl_Loop_Data *pd)
{
Filter *f;
Ecore_Event_Message_Handler_Data *eemhd;
Eo *ecore_event_handler = efl_loop_message_handler_get
(EFL_LOOP_CLASS, obj, ECORE_EVENT_MESSAGE_HANDLER_CLASS);
if (!ecore_event_handler) return;
eemhd = efl_data_scope_get(ecore_event_handler, MY_CLASS);
if (!eemhd) return;
if (!eemhd->filters) return;
eemhd->filters_walking++;
EINA_INLIST_FOREACH(eemhd->filters, f)
{
if (f->delete_me) continue;
if (f->func_start) f->loop_data = f->func_start(f->data);
}
_efl_loop_messages_filter(obj, pd, eemhd);
EINA_INLIST_FOREACH(eemhd->filters, f)
{
if (f->delete_me) continue;
if (f->func_end) f->func_end(f->data, f->loop_data);
}
eemhd->filters_walking--;
if (eemhd->filters_walking == 0)
{
EINA_LIST_FREE(eemhd->filters_delete, f)
{
free(f);
}
}
}
//////////////////////////////////////////////////////////////////////////
EOLIAN static Ecore_Event_Message *
_ecore_event_message_handler_message_type_add(Eo *obj, Ecore_Event_Message_Handler_Data *pd EINA_UNUSED)
{
// XXX: implemented event obj cache
return efl_add(ECORE_EVENT_MESSAGE_CLASS, obj);
}
EOLIAN static int
_ecore_event_message_handler_type_new(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd)
{
Eina_Inlist **tmp;
int evnum;
evnum = pd->event_type_count + 1;
tmp = realloc(pd->handlers, sizeof(Eina_Inlist *) * (evnum + 1));
if (!tmp) return 0;
pd->handlers = tmp;
pd->handlers[evnum] = NULL;
pd->event_type_count = evnum;
return evnum;
}
EOLIAN static void *
_ecore_event_message_handler_handler_add(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd, int type, void *func, void *data)
{
Handler *h;
if ((type < 0) || (type > pd->event_type_count) || (!func)) return NULL;
h = calloc(1, sizeof(Handler));
if (!h) return NULL;
h->func = func;
h->data = data;
h->type = type;
if (pd->current_event_type == type)
{
h->to_add = EINA_TRUE;
pd->handlers_add = eina_list_append(pd->handlers_add, h);
}
else
pd->handlers[type] = eina_inlist_append(pd->handlers[type],
EINA_INLIST_GET(h));
return h;
}
EOLIAN static void *
_ecore_event_message_handler_handler_del(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd, void *handler)
{
Handler *h = handler;
void *data;
if (!h) return NULL;
if ((h->type < 0) || (h->type > pd->event_type_count)) return NULL;
data = h->data;
if (pd->handlers_walking > 0)
{
h->delete_me = EINA_TRUE;
pd->handlers_delete = eina_list_append(pd->handlers_delete, h);
}
else
{
if (h->to_add)
pd->handlers_add = eina_list_remove(pd->handlers_add, h);
else
pd->handlers[h->type] = eina_inlist_remove(pd->handlers[h->type],
EINA_INLIST_GET(h));
free(h);
}
return data;
}
EOLIAN static void *
_ecore_event_message_handler_handler_data_get(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd EINA_UNUSED, void *handler)
{
Handler *h = handler;
if (!h) return NULL;
return h->data;
}
EOLIAN static void *
_ecore_event_message_handler_handler_data_set(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd EINA_UNUSED, void *handler, void *data)
{
Handler *h = handler;
void *prev_data;
if (!h) return NULL;
prev_data = h->data;
h->data = data;
return prev_data;
}
EOLIAN static void *
_ecore_event_message_handler_filter_add(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd, void *func_start, void *func_filter, void *func_end, void *data)
{
Filter *f;
if (!func_filter) return NULL;
f = calloc(1, sizeof(Filter));
if (!f) return NULL;
f->func_start = func_start;
f->func_filter = func_filter;
f->func_end = func_end;
f->data = data;
pd->filters = eina_inlist_append(pd->filters, EINA_INLIST_GET(f));
return f;
}
EOLIAN static void *
_ecore_event_message_handler_filter_del(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd, void *filter)
{
Filter *f = filter;
void *data;
if (!f) return NULL;
data = f->data;
if (pd->filters_walking > 0)
{
f->delete_me = EINA_TRUE;
pd->filters_delete = eina_list_append(pd->filters_delete, f);
}
else
{
pd->filters = eina_inlist_remove(pd->filters, EINA_INLIST_GET(f));
free(f);
}
return data;
}
EOLIAN static int
_ecore_event_message_handler_current_type_get(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd)
{
return pd->current_event_type;
}
EOLIAN static void *
_ecore_event_message_handler_current_event_get(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd)
{
return pd->current_event_data;
}
EOLIAN static Efl_Object *
_ecore_event_message_handler_efl_object_constructor(Eo *obj, Ecore_Event_Message_Handler_Data *pd)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
pd->event_type_count = -1;
pd->current_event_type = -1;
return obj;
}
EOLIAN static void
_ecore_event_message_handler_efl_object_destructor(Eo *obj, Ecore_Event_Message_Handler_Data *pd)
{
Handler *h;
int i;
if (pd->handlers_walking == 0)
{
EINA_LIST_FREE(pd->handlers_delete, h)
{
pd->handlers[h->type] =
eina_inlist_remove(pd->handlers[h->type],
EINA_INLIST_GET(h));
free(h);
}
EINA_LIST_FREE(pd->handlers_add, h)
{
free(h);
}
for (i = 0; i < pd->event_type_count; i++)
{
EINA_INLIST_FREE(pd->handlers[i], h) free(h);
}
free(pd->handlers);
pd->handlers = NULL;
}
else
{
ERR("Destruction of ecore_event_message_handler while walking events");
}
efl_destructor(efl_super(obj, MY_CLASS));
}
EOLIAN static void
_ecore_event_message_handler_efl_loop_message_handler_message_call(Eo *obj, Ecore_Event_Message_Handler_Data *pd, Efl_Loop_Message *message)
{
Handler *h;
int type = -1;
void *data = NULL, *free_func = NULL, *free_data = NULL;
Ecore_End_Cb fn_free = NULL;
Eina_List *l, *l2;
int handled = 0;
// call legacy handlers which are controled by this class' custom api
ecore_event_message_data_steal
(message, &type, &data, &free_func, &free_data);
if ((type >= 0) && (type <= pd->event_type_count))
{
if (free_func) fn_free = free_func;
pd->current_event_data = data;
pd->current_event_type = type;
pd->handlers_walking++;
EINA_INLIST_FOREACH(pd->handlers[type], h)
{
if (h->delete_me) continue;
handled++;
if (!h->func(h->data, h->type, data)) break;
}
pd->handlers_walking--;
pd->current_event_data = NULL;
pd->current_event_type = -1;
EINA_LIST_FOREACH_SAFE(pd->handlers_add, l, l2, h)
{
if (h->type == type)
{
h->to_add = EINA_FALSE;
pd->handlers_add =
eina_list_remove_list(pd->handlers_add, l);
pd->handlers[type] =
eina_inlist_append(pd->handlers[type], EINA_INLIST_GET(h));
}
}
if (pd->handlers_walking == 0)
{
EINA_LIST_FREE(pd->handlers_delete, h)
{
if (h->to_add)
pd->handlers_add = eina_list_remove(pd->handlers_add, h);
else
pd->handlers[h->type] =
eina_inlist_remove(pd->handlers[h->type],
EINA_INLIST_GET(h));
free(h);
}
}
if ((type == ECORE_EVENT_SIGNAL_EXIT) && (handled == 0))
{
Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
if (loop)
{
Eina_Value v = EINA_VALUE_EMPTY;
int val = 0;
eina_value_setup(&v, EINA_VALUE_TYPE_INT);
eina_value_set(&v, &val);
efl_loop_quit(loop, v);
}
}
}
efl_event_callback_call
(obj, ECORE_EVENT_MESSAGE_HANDLER_EVENT_MESSAGE_ECORE_EVENT, message);
efl_loop_message_handler_message_call
(efl_super(obj, MY_CLASS), message);
if (data)
{
if (fn_free) fn_free(free_data, data);
else free(data);
}
}
static Eina_Bool
_flush_cb(void *data, void *handler EINA_UNUSED, void *message)
{
int *type = data;
int evtype = -1;
void *evdata = NULL, *free_func = NULL, *free_data = NULL;
Ecore_End_Cb fn_free = NULL;
if (!efl_isa(message, ECORE_EVENT_MESSAGE_CLASS)) return EINA_TRUE;
ecore_event_message_data_steal(message, &evtype, &evdata, &free_func, &free_data);
if (*type != evtype) return EINA_TRUE;
if (free_func)
{
fn_free = free_func;
fn_free(free_data, evdata);
}
return EINA_FALSE;
}
EOLIAN static void
_ecore_event_message_handler_type_flush(Eo *obj, Ecore_Event_Message_Handler_Data *pd EINA_UNUSED, int type)
{
Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
Efl_Loop_Data *loop_data = efl_data_scope_get(loop, EFL_LOOP_CLASS);
if (loop && loop_data)
{
_efl_loop_messages_call(loop, loop_data, _flush_cb, &type);
}
}
//////////////////////////////////////////////////////////////////////////
#include "ecore_event_message_handler.eo.c"

View File

@ -0,0 +1,86 @@
import efl_types;
import eina_types;
class Ecore.Event.Message.Handler (Efl.Loop.Message.Handler)
{
[[ For Legacy API usage Only
This class is rather hacky/messy as it's really internal glue
to handle legacy ecore events alongside the new loop message
stuff merged together. This is ugly as it's internal only
to quickly glue things together and is destined for death in
EFL 2.0 or when we dump legacy.
]]
methods {
message_type_add {
[[ ]]
return: Ecore.Event.Message; [[ ]]
}
type_new {
[[ ]]
return: int; [[ ]]
}
handler_add {
[[ Legacy list of callback handlers so they can return false ]]
params {
type: int;
func: void_ptr;
data: void_ptr;
}
return: void_ptr; [[ Lazy return handle ]]
}
handler_del {
params {
handler: void_ptr; [[ handler returned from handler_add() ]]
}
return: void_ptr; [[ handler data ptr ]]
}
handler_data_get {
params {
handler: void_ptr; [[ handler returned from handler_add() ]]
}
return: void_ptr; [[ handler data ptr ]]
}
handler_data_set {
params {
handler: void_ptr; [[ handler returned from handler_add() ]]
data: void_ptr;
}
return: void_ptr; [[ prev handler data ptr ]]
}
filter_add {
[[ Legacy event filter ]]
params {
func_start: void_ptr;
func_filter: void_ptr;
func_end: void_ptr;
data: void_ptr;
}
return: void_ptr; [[ Lazy return filter handle ]]
}
filter_del {
params {
filter: void_ptr; [[ filter returned from filter_add() ]]
}
return: void_ptr; [[ filter data ptr ]]
}
current_type_get {
return: int; [[ ]]
}
current_event_get {
return: void_ptr; [[ ]]
}
type_flush {
params {
type: int; [[ the event type to flush ]]
}
}
}
events {
message,ecore,event: Ecore.Event.Message; [[ Sample - override this ]]
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
Efl.Loop.Message.Handler.message_call; [[ Sample - override this ]]
}
}

View File

@ -7,47 +7,6 @@
#include "Ecore.h"
#include "ecore_private.h"
static int inpurge = 0;
struct _Ecore_Event_Handler
{
EINA_INLIST;
ECORE_MAGIC;
int type;
Ecore_Event_Handler_Cb func;
void *data;
int references;
Eina_Bool delete_me : 1;
};
GENERIC_ALLOC_SIZE_DECLARE(Ecore_Event_Handler);
struct _Ecore_Event_Filter
{
EINA_INLIST;
ECORE_MAGIC;
Ecore_Data_Cb func_start;
Ecore_Filter_Cb func_filter;
Ecore_End_Cb func_end;
void *loop_data;
void *data;
int references;
Eina_Bool delete_me : 1;
};
GENERIC_ALLOC_SIZE_DECLARE(Ecore_Event_Filter);
struct _Ecore_Event
{
EINA_INLIST;
ECORE_MAGIC;
int type;
void *event;
Ecore_End_Cb func_free;
void *data;
int references;
Eina_Bool delete_me : 1;
};
GENERIC_ALLOC_SIZE_DECLARE(Ecore_Event);
typedef struct _Ecore_Future_Schedule_Entry
{
Eina_Future_Schedule_Entry base;
@ -57,131 +16,45 @@ typedef struct _Ecore_Future_Schedule_Entry
Eina_Value value;
} Ecore_Future_Schedule_Entry;
static int events_num = 0;
static Ecore_Event *events = NULL;
static Ecore_Event *event_current = NULL;
static Ecore_Event *purge_events = NULL;
//////
// XXX: still using legacy ecore events
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 Ecore_Event_Handler **event_handlers = NULL;
static Ecore_Event_Handler *event_handler_current = NULL;
static int event_handlers_num = 0;
static int event_handlers_alloc_num = 0;
static Eina_List *event_handlers_delete_list = NULL;
static Ecore_Event_Handler *event_handlers_add_list = NULL;
static Ecore_Event_Filter *event_filters = NULL;
static Ecore_Event_Filter *event_filter_current = NULL;
static Ecore_Event *event_filter_event_current = NULL;
static int event_filters_delete_me = 0;
static int event_id_max = ECORE_EVENT_COUNT;
static int ecore_raw_event_type = ECORE_EVENT_NONE;
static void *ecore_raw_event_event = NULL;
static Ecore_Event_Handler *future_handler = NULL;
static int ECORE_EV_FUTURE_ID = -1;
static Eina_Mempool *mp_future_schedule_entry = NULL;
static Eina_Bool shutting_down = EINA_FALSE;
static void _ecore_event_purge_deleted(void);
static void *_ecore_event_del(Ecore_Event *event);
static Ecore_Event_Message_Handler *_event_msg_handler = NULL;
EAPI Ecore_Event_Handler *
ecore_event_handler_add(int type,
Ecore_Event_Handler_Cb func,
const void *data)
{
Ecore_Event_Handler *eh = NULL;
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
if (!func) return NULL;
if ((type <= ECORE_EVENT_NONE) || (type >= event_id_max)) return NULL;
eh = ecore_event_handler_calloc(1);
if (!eh) return NULL;
ECORE_MAGIC_SET(eh, ECORE_MAGIC_EVENT_HANDLER);
eh->type = type;
eh->func = func;
eh->data = (void *)data;
if (type >= (event_handlers_num - 1))
{
int p_alloc_num;
p_alloc_num = event_handlers_alloc_num;
event_handlers_num = type + 1;
if (event_handlers_num > event_handlers_alloc_num)
{
Ecore_Event_Handler **new_handlers;
int i;
event_handlers_alloc_num = ((event_handlers_num + 16) / 16) * 16;
new_handlers = realloc(event_handlers, event_handlers_alloc_num * sizeof(Ecore_Event_Handler *));
if (!new_handlers)
{
ecore_event_handler_mp_free(eh);
return NULL;
}
event_handlers = new_handlers;
for (i = p_alloc_num; i < event_handlers_alloc_num; i++)
event_handlers[i] = NULL;
}
}
if (ecore_raw_event_type == type)
event_handlers_add_list = (Ecore_Event_Handler *)eina_inlist_append(EINA_INLIST_GET(event_handlers_add_list), EINA_INLIST_GET(eh));
else if (type < event_handlers_alloc_num)
event_handlers[type] = (Ecore_Event_Handler *)eina_inlist_append(EINA_INLIST_GET(event_handlers[type]), EINA_INLIST_GET(eh));
return eh;
return ecore_event_message_handler_add(_event_msg_handler,
type, func, (void *)data);
}
EAPI void *
ecore_event_handler_del(Ecore_Event_Handler *event_handler)
{
if (!event_handler) return NULL;
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
if (!ECORE_MAGIC_CHECK(event_handler, ECORE_MAGIC_EVENT_HANDLER))
{
ECORE_MAGIC_FAIL(event_handler, ECORE_MAGIC_EVENT_HANDLER,
"ecore_event_handler_del");
return NULL;
}
return _ecore_event_handler_del(event_handler);
return ecore_event_message_handler_del(_event_msg_handler,
event_handler);
}
EAPI void *
ecore_event_handler_data_get(Ecore_Event_Handler *eh)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
if (!ECORE_MAGIC_CHECK(eh, ECORE_MAGIC_EVENT_HANDLER))
{
ECORE_MAGIC_FAIL(eh, ECORE_MAGIC_EVENT_HANDLER, "ecore_event_handler_data_get");
return NULL;
}
return eh->data;
return ecore_event_message_handler_data_get(_event_msg_handler, eh);
}
EAPI void *
ecore_event_handler_data_set(Ecore_Event_Handler *eh,
const void *data)
{
void *old = NULL;
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
if (!ECORE_MAGIC_CHECK(eh, ECORE_MAGIC_EVENT_HANDLER))
{
ECORE_MAGIC_FAIL(eh, ECORE_MAGIC_EVENT_HANDLER, "ecore_event_handler_data_set");
return NULL;
}
old = eh->data;
eh->data = (void *)data;
return old;
}
static void
_ecore_event_generic_free(void *data EINA_UNUSED,
void *event)
{ /* DO NOT MEMPOOL FREE THIS */
free(event);
return ecore_event_message_handler_data_set(_event_msg_handler, eh,
(void *)data);
}
EAPI Ecore_Event *
@ -190,34 +63,27 @@ ecore_event_add(int type,
Ecore_End_Cb func_free,
void *data)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
Ecore_Event_Message *msg;
if (type <= ECORE_EVENT_NONE) return NULL;
if (type >= event_id_max) return NULL;
if ((ev) && (!func_free)) func_free = _ecore_event_generic_free;
return _ecore_event_add(type, ev, func_free, data);
msg = ecore_event_message_handler_message_type_add(_event_msg_handler);
ecore_event_message_data_set(msg, type, ev, func_free, data);
efl_loop_message_handler_message_send(_event_msg_handler, msg);
return (Ecore_Event *)msg;
}
EAPI void *
ecore_event_del(Ecore_Event *event)
{
if (!event) return NULL;
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
if (!ECORE_MAGIC_CHECK(event, ECORE_MAGIC_EVENT))
{
ECORE_MAGIC_FAIL(event, ECORE_MAGIC_EVENT, "ecore_event_del");
return NULL;
}
EINA_SAFETY_ON_TRUE_RETURN_VAL(event->delete_me, NULL);
event->delete_me = 1;
return event->data;
void *data = NULL;
ecore_event_message_data_get((Eo *)event, NULL, &data, NULL, NULL);
_efl_loop_message_unsend((Eo *)event);
return data;
}
EAPI int
ecore_event_type_new(void)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
return event_id_max++;
return ecore_event_message_handler_type_new(_event_msg_handler);
}
EAPI Ecore_Event_Filter *
@ -226,59 +92,27 @@ ecore_event_filter_add(Ecore_Data_Cb func_start,
Ecore_End_Cb func_end,
const void *data)
{
Ecore_Event_Filter *ef = NULL;
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
if (!func_filter) return NULL;
ef = ecore_event_filter_calloc(1);
if (!ef) return NULL;
ECORE_MAGIC_SET(ef, ECORE_MAGIC_EVENT_FILTER);
ef->func_start = func_start;
ef->func_filter = func_filter;
ef->func_end = func_end;
ef->data = (void *)data;
event_filters = (Ecore_Event_Filter *)eina_inlist_append(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(ef));
return ef;
return ecore_event_message_handler_filter_add(_event_msg_handler,
func_start, func_filter,
func_end, (void *)data);
}
EAPI void *
ecore_event_filter_del(Ecore_Event_Filter *ef)
{
if (!ef) return NULL;
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
if (!ECORE_MAGIC_CHECK(ef, ECORE_MAGIC_EVENT_FILTER))
{
ECORE_MAGIC_FAIL(ef, ECORE_MAGIC_EVENT_FILTER, "ecore_event_filter_del");
return NULL;
}
EINA_SAFETY_ON_TRUE_RETURN_VAL(ef->delete_me, NULL);
ef->delete_me = 1;
event_filters_delete_me = 1;
return ef->data;
return ecore_event_message_handler_filter_del(_event_msg_handler, ef);
}
EAPI int
ecore_event_current_type_get(void)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
return ecore_raw_event_type;
return ecore_event_message_handler_current_type_get(_event_msg_handler);
}
EAPI void *
ecore_event_current_event_get(void)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
return ecore_raw_event_event;
}
EAPI void *
_ecore_event_handler_del(Ecore_Event_Handler *event_handler)
{
EINA_SAFETY_ON_TRUE_RETURN_VAL(event_handler->delete_me, NULL);
event_handler->delete_me = 1;
event_handlers_delete_list = eina_list_append(event_handlers_delete_list, event_handler);
return event_handler->data;
return ecore_event_message_handler_current_event_get(_event_msg_handler);
}
static Eina_Bool
@ -294,12 +128,6 @@ static void
ecore_future_free(void *user_data, void *func_data EINA_UNUSED)
{
Ecore_Future_Schedule_Entry *entry = user_data;
/*
In case entry->event is not NULL, it means
that ecore is shutting down. In this case,
we must cancel the future otherwise Eina may
try to use it and lead to crashes.
*/
if (entry->event)
{
eina_future_cancel(entry->future);
@ -355,6 +183,44 @@ _ecore_event_init(void)
const char *choice = getenv("EINA_MEMPOOL");
if ((!choice) || (!choice[0])) choice = "chained_mempool";
_event_msg_handler =
efl_loop_message_handler_get(EFL_LOOP_CLASS,
_mainloop_singleton,
ECORE_EVENT_MESSAGE_HANDLER_CLASS);
if (!_event_msg_handler)
{
ERR("Cannot create legacy ecore event message handler");
return EINA_FALSE;
}
// init some core legacy event types in t he same order and numbering as before
// ECORE_EVENT_NONE 0
// no need to do as ev types start at 1
// ECORE_EVENT_SIGNAL_USER 1
ecore_event_message_handler_type_new(_event_msg_handler);
// ECORE_EVENT_SIGNAL_HUP 2
ecore_event_message_handler_type_new(_event_msg_handler);
// ECORE_EVENT_SIGNAL_EXIT 3
ecore_event_message_handler_type_new(_event_msg_handler);
// ECORE_EVENT_SIGNAL_POWER 4
ecore_event_message_handler_type_new(_event_msg_handler);
// ECORE_EVENT_SIGNAL_REALTIME 5
ecore_event_message_handler_type_new(_event_msg_handler);
// ECORE_EVENT_MEMORY_STATE 6
ecore_event_message_handler_type_new(_event_msg_handler);
// ECORE_EVENT_POWER_STATE 7
ecore_event_message_handler_type_new(_event_msg_handler);
// ECORE_EVENT_LOCALE_CHANGED 8
ecore_event_message_handler_type_new(_event_msg_handler);
// ECORE_EVENT_HOSTNAME_CHANGED 9
ecore_event_message_handler_type_new(_event_msg_handler);
// ECORE_EVENT_SYSTEM_TIMEDATE_CHANGED 10
ecore_event_message_handler_type_new(_event_msg_handler);
// ECORE_EVENT_COUNT 11
// no need to do as it was a count, nto an event
//////
// 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);
@ -364,6 +230,8 @@ _ecore_event_init(void)
NULL, sizeof(Ecore_Future_Schedule_Entry),
512);
EINA_SAFETY_ON_NULL_GOTO(mp_future_schedule_entry, err_pool);
//
//////
return EINA_TRUE;
@ -378,337 +246,42 @@ _ecore_event_init(void)
void
_ecore_event_shutdown(void)
{
int i;
Ecore_Event_Handler *eh;
Ecore_Event_Filter *ef;
shutting_down = EINA_TRUE;
//////
// XXX: ecore future still using legacy...
ecore_event_handler_del(future_handler);
future_handler = NULL;
while (events) _ecore_event_del(events);
event_current = NULL;
for (i = 0; i < event_handlers_num; i++)
{
while ((eh = event_handlers[i]))
{
event_handlers[i] = (Ecore_Event_Handler *)eina_inlist_remove(EINA_INLIST_GET(event_handlers[i]), EINA_INLIST_GET(event_handlers[i]));
ECORE_MAGIC_SET(eh, ECORE_MAGIC_NONE);
if (!eh->delete_me) ecore_event_handler_mp_free(eh);
}
}
EINA_LIST_FREE(event_handlers_delete_list, eh)
ecore_event_handler_mp_free(eh);
if (event_handlers) free(event_handlers);
event_handlers = NULL;
event_handlers_num = 0;
event_handlers_alloc_num = 0;
while ((ef = event_filters))
{
event_filters = (Ecore_Event_Filter *)eina_inlist_remove(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(event_filters));
ECORE_MAGIC_SET(ef, ECORE_MAGIC_NONE);
ecore_event_filter_mp_free(ef);
}
event_filters_delete_me = 0;
event_filter_current = NULL;
event_filter_event_current = NULL;
ECORE_EV_FUTURE_ID = -1;
}
//
//////
int
_ecore_event_exist(void)
{
Ecore_Event *e;
EINA_INLIST_FOREACH(events, e)
if (!e->delete_me) return 1;
return 0;
}
Ecore_Event *
_ecore_event_add(int type,
void *ev,
Ecore_End_Cb func_free,
void *data)
{
Ecore_Event *e;
e = ecore_event_calloc(1);
if (!e) return NULL;
ECORE_MAGIC_SET(e, ECORE_MAGIC_EVENT);
e->type = type;
e->event = ev;
e->func_free = func_free;
e->data = data;
if (inpurge > 0)
{
purge_events = (Ecore_Event *)eina_inlist_append(EINA_INLIST_GET(purge_events), EINA_INLIST_GET(e));
events_num++;
}
else
{
events = (Ecore_Event *)eina_inlist_append(EINA_INLIST_GET(events), EINA_INLIST_GET(e));
events_num++;
}
return e;
}
void *
_ecore_event_del(Ecore_Event *event)
{
void *data;
data = event->data;
if (event->func_free) _ecore_call_end_cb(event->func_free, event->data, event->event);
events = (Ecore_Event *)eina_inlist_remove(EINA_INLIST_GET(events), EINA_INLIST_GET(event));
ECORE_MAGIC_SET(event, ECORE_MAGIC_NONE);
ecore_event_mp_free(event);
events_num--;
return data;
}
static void
_ecore_event_purge_deleted(void)
{
Ecore_Event *itr = events;
inpurge++;
while (itr)
{
Ecore_Event *next = (Ecore_Event *)EINA_INLIST_GET(itr)->next;
if ((!itr->references) && (itr->delete_me))
_ecore_event_del(itr);
itr = next;
}
inpurge--;
while (purge_events)
{
Ecore_Event *e = purge_events;
purge_events = (Ecore_Event *)eina_inlist_remove(EINA_INLIST_GET(purge_events), EINA_INLIST_GET(purge_events));
events = (Ecore_Event *)eina_inlist_append(EINA_INLIST_GET(events), EINA_INLIST_GET(e));
}
}
static inline void
_ecore_event_filters_apply(void)
{
if (!event_filter_current)
{
/* regular main loop, start from head */
event_filter_current = event_filters;
}
else
{
/* recursive main loop, continue from where we were */
event_filter_current = (Ecore_Event_Filter *)EINA_INLIST_GET(event_filter_current)->next;
}
if ((!event_filter_current) && (!event_filters_delete_me) && (!purge_events)) return;
eina_evlog("+event_filter", NULL, 0.0, NULL);
while (event_filter_current)
{
Ecore_Event_Filter *ef = event_filter_current;
if (!ef->delete_me)
{
ef->references++;
if (ef->func_start)
ef->loop_data = _ecore_call_data_cb(ef->func_start, ef->data);
if (!event_filter_event_current)
{
/* regular main loop, start from head */
event_filter_event_current = events;
}
else
{
/* recursive main loop, continue from where we were */
event_filter_event_current = (Ecore_Event *)EINA_INLIST_GET(event_filter_event_current)->next;
}
while (event_filter_event_current)
{
Ecore_Event *e = event_filter_event_current;
if (!_ecore_call_filter_cb(ef->func_filter, ef->data,
ef->loop_data, e->type, e->event))
{
ecore_event_del(e);
}
if (event_filter_event_current) /* may have changed in recursive main loops */
event_filter_event_current = (Ecore_Event *)EINA_INLIST_GET(event_filter_event_current)->next;
}
if (ef->func_end)
_ecore_call_end_cb(ef->func_end, ef->data, ef->loop_data);
ef->references--;
}
if (event_filter_current) /* may have changed in recursive main loops */
event_filter_current = (Ecore_Event_Filter *)EINA_INLIST_GET(event_filter_current)->next;
}
eina_evlog("-event_filter", NULL, 0.0, NULL);
if (event_filters_delete_me)
{
int deleted_in_use = 0;
Ecore_Event_Filter *l;
for (l = event_filters; l; )
{
Ecore_Event_Filter *ef = l;
l = (Ecore_Event_Filter *)EINA_INLIST_GET(l)->next;
if (ef->delete_me)
{
if (ef->references)
{
deleted_in_use++;
continue;
}
event_filters = (Ecore_Event_Filter *)eina_inlist_remove(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(ef));
ECORE_MAGIC_SET(ef, ECORE_MAGIC_NONE);
ecore_event_filter_mp_free(ef);
}
}
if (!deleted_in_use)
event_filters_delete_me = 0;
}
}
void
_ecore_event_call(void)
{
Eina_List *l, *l_next;
Ecore_Event_Handler *eh;
_ecore_event_filters_apply();
if (!event_current)
{
/* regular main loop, start from head */
event_current = events;
event_handler_current = NULL;
}
if ((!event_current) && (!event_handlers_delete_list)) return;
eina_evlog("+events", NULL, 0.0, NULL);
while (event_current)
{
Ecore_Event *e = event_current;
int handle_count = 0;
if (e->delete_me)
{
event_current = (Ecore_Event *)EINA_INLIST_GET(event_current)->next;
continue;
}
ecore_raw_event_type = e->type;
ecore_raw_event_event = e->event;
e->references++;
if ((e->type >= 0) && (e->type < event_handlers_num))
{
if (!event_handler_current)
{
/* regular main loop, start from head */
event_handler_current = event_handlers[e->type];
}
else
{
/* recursive main loop, continue from where we were */
event_handler_current = (Ecore_Event_Handler *)EINA_INLIST_GET(event_handler_current)->next;
}
while ((event_handler_current) && (!e->delete_me))
{
eh = event_handler_current;
if (!eh->delete_me)
{
Eina_Bool ret;
handle_count++;
eh->references++;
ret = _ecore_call_handler_cb(eh->func, eh->data, e->type, e->event);
eh->references--;
if (!ret)
{
event_handler_current = NULL;
break; /* 0 == "call no further handlers" */
}
}
if (event_handler_current) /* may have changed in recursive main loops */
event_handler_current = (Ecore_Event_Handler *)EINA_INLIST_GET(event_handler_current)->next;
}
}
while (event_handlers_add_list)
{
eh = event_handlers_add_list;
event_handlers_add_list = (Ecore_Event_Handler *)eina_inlist_remove(EINA_INLIST_GET(event_handlers_add_list), EINA_INLIST_GET(eh));
event_handlers[eh->type] = (Ecore_Event_Handler *)eina_inlist_append(EINA_INLIST_GET(event_handlers[eh->type]), EINA_INLIST_GET(eh));
}
/* if no handlers were set for EXIT signal - then default is */
/* to quit the main loop */
if ((e->type == ECORE_EVENT_SIGNAL_EXIT) && (handle_count == 0))
ecore_main_loop_quit();
e->references--;
e->delete_me = 1;
if (event_current) /* may have changed in recursive main loops */
event_current = (Ecore_Event *)EINA_INLIST_GET(event_current)->next;
}
eina_evlog("-events", NULL, 0.0, NULL);
ecore_raw_event_type = ECORE_EVENT_NONE;
ecore_raw_event_event = NULL;
_ecore_event_purge_deleted();
EINA_LIST_FOREACH_SAFE(event_handlers_delete_list, l, l_next, eh)
{
if (eh->references) continue;
event_handlers_delete_list = eina_list_remove_list(event_handlers_delete_list, l);
event_handlers[eh->type] = (Ecore_Event_Handler *)eina_inlist_remove(EINA_INLIST_GET(event_handlers[eh->type]), EINA_INLIST_GET(eh));
ECORE_MAGIC_SET(eh, ECORE_MAGIC_NONE);
ecore_event_handler_mp_free(eh);
}
efl_loop_message_handler_message_clear(_event_msg_handler);
_event_msg_handler = NULL;
}
void *
_ecore_event_signal_user_new(void)
{
Ecore_Event_Signal_User *e;
e = calloc(1, sizeof(Ecore_Event_Signal_User));
return e;
return calloc(1, sizeof(Ecore_Event_Signal_User));
}
void *
_ecore_event_signal_hup_new(void)
{
Ecore_Event_Signal_Hup *e;
e = calloc(1, sizeof(Ecore_Event_Signal_Hup));
return e;
return calloc(1, sizeof(Ecore_Event_Signal_Hup));
}
void *
_ecore_event_signal_exit_new(void)
{
Ecore_Event_Signal_Exit *e;
e = calloc(1, sizeof(Ecore_Event_Signal_Exit));
return e;
return calloc(1, sizeof(Ecore_Event_Signal_Exit));
}
void *
_ecore_event_signal_power_new(void)
{
Ecore_Event_Signal_Power *e;
e = calloc(1, sizeof(Ecore_Event_Signal_Power));
return e;
return calloc(1, sizeof(Ecore_Event_Signal_Power));
}
void *
@ -720,58 +293,17 @@ _ecore_event_signal_realtime_new(void)
EAPI void
ecore_event_type_flush_internal(int type, ...)
{
Eina_Inarray types;
Ecore_Event *event;
Eina_Inlist *l;
int *itr;
va_list args;
Eina_Bool wrong_type = EINA_FALSE;
// In case of an empty list of event
if (type == ECORE_EVENT_NONE) return;
eina_inarray_step_set(&types, sizeof (Eina_Inarray), sizeof (int), 4);
eina_inarray_push(&types, &type);
ecore_event_message_handler_type_flush(_event_msg_handler, type);
va_start(args, type);
do
for (;;)
{
type = va_arg(args, int);
if (type == ECORE_EVENT_NONE) break ;
eina_inarray_push(&types, &type);
if (type == ECORE_EVENT_NONE) break;
ecore_event_message_handler_type_flush(_event_msg_handler, type);
}
while (1);
va_end(args);
EINA_INARRAY_FOREACH(&types, itr)
{
if (*itr >= 0 && *itr < event_id_max) continue;
ERR("Invalid event flush requested: %i", *itr);
wrong_type = EINA_TRUE;
}
if (wrong_type)
{
eina_inarray_flush(&types);
return ;
}
EINA_INLIST_FOREACH_SAFE((Eina_Inlist *) events, l, event)
{
Eina_Bool found = EINA_FALSE;
EINA_INARRAY_FOREACH(&types, itr)
if (event->type == *itr)
found = EINA_TRUE;
if (!found) continue ;
if (event->delete_me) continue ;
event->delete_me = 1;
}
_ecore_event_purge_deleted();
eina_inarray_flush(&types);
}

View File

@ -38,8 +38,6 @@ EAPI int ECORE_EXE_EVENT_DEL = 0;
EAPI int ECORE_EXE_EVENT_DATA = 0;
EAPI int ECORE_EXE_EVENT_ERROR = 0;
Eina_List *_ecore_exe_exes = NULL;
EAPI void
ecore_exe_run_priority_set(int pri)
{
@ -63,18 +61,19 @@ ecore_exe_run(const char *exe_cmd,
}
EAPI Ecore_Exe *
ecore_exe_pipe_run(const char *exe_cmd,
Ecore_Exe_Flags flags,
const void *data)
ecore_exe_pipe_run(const char *exe_cmd,
Ecore_Exe_Flags flags,
const void *data)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
Ecore_Exe *ret = efl_add(MY_CLASS, NULL, ecore_obj_exe_command_set(efl_added, exe_cmd, flags));
Ecore_Exe *ret = efl_add(MY_CLASS, efl_loop_main_get(EFL_LOOP_CLASS),
ecore_obj_exe_command_set(efl_added, exe_cmd,
flags));
if (ret)
{
Ecore_Exe_Data *pd = efl_data_scope_get(ret, MY_CLASS);
pd->data = (void *) data;
}
return ret;
}
@ -98,10 +97,7 @@ _ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
obj = efl_finalize(efl_super(obj, MY_CLASS));
if (!obj)
return obj;
if (!obj) return obj;
return _impl_ecore_exe_efl_object_finalize(obj, exe);
}
@ -111,8 +107,7 @@ ecore_exe_callback_pre_free_set(Ecore_Exe *obj,
{
EINA_MAIN_LOOP_CHECK_RETURN;
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return;
if (!efl_isa(obj, MY_CLASS)) return;
exe->pre_free_cb = func;
}
@ -123,18 +118,15 @@ ecore_exe_send(Ecore_Exe *obj,
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE);
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return EINA_FALSE;
if (!efl_isa(obj, MY_CLASS)) return EINA_FALSE;
EINA_SAFETY_ON_TRUE_RETURN_VAL(size == 0, EINA_TRUE);
if (exe->close_stdin)
{
ERR("Ecore_Exe %p stdin is closed! Cannot send %d bytes from %p",
exe, size, data);
return EINA_FALSE;
}
{
ERR("Ecore_Exe %p stdin is closed! Cannot send %d bytes from %p",
exe, size, data);
return EINA_FALSE;
}
return _impl_ecore_exe_send(obj, exe, data, size);
}
@ -143,9 +135,7 @@ ecore_exe_close_stdin(Ecore_Exe *obj)
{
EINA_MAIN_LOOP_CHECK_RETURN;
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return;
if (!efl_isa(obj, MY_CLASS)) return;
exe->close_stdin = 1;
}
@ -158,10 +148,9 @@ ecore_exe_auto_limits_set(Ecore_Exe *obj,
{
EINA_MAIN_LOOP_CHECK_RETURN;
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return;
_impl_ecore_exe_auto_limits_set(obj, exe, start_bytes, end_bytes, start_lines, end_lines);
if (!efl_isa(obj, MY_CLASS)) return;
_impl_ecore_exe_auto_limits_set(obj, exe, start_bytes, end_bytes,
start_lines, end_lines);
}
EAPI Ecore_Exe_Event_Data *
@ -170,9 +159,7 @@ ecore_exe_event_data_get(Ecore_Exe *obj,
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return NULL;
if (!efl_isa(obj, MY_CLASS)) return NULL;
return _impl_ecore_exe_event_data_get(obj, exe, flags);
}
@ -182,14 +169,10 @@ ecore_exe_tag_set(Ecore_Exe *obj,
{
EINA_MAIN_LOOP_CHECK_RETURN;
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return;
if (!efl_isa(obj, MY_CLASS)) return;
IF_FREE(exe->tag);
if (tag)
exe->tag = strdup(tag);
else
exe->tag = NULL;
if (tag) exe->tag = strdup(tag);
else exe->tag = NULL;
}
EAPI const char *
@ -197,9 +180,7 @@ ecore_exe_tag_get(const Ecore_Exe *obj)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return NULL;
if (!efl_isa(obj, MY_CLASS)) return NULL;
return exe->tag;
}
@ -208,12 +189,9 @@ ecore_exe_free(Ecore_Exe *obj)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return NULL;
if (!efl_isa(obj, MY_CLASS)) return NULL;
void *data = exe->data;
efl_del(obj);
return data;
}
@ -221,7 +199,6 @@ EOLIAN static void
_ecore_exe_efl_object_destructor(Eo *obj, Ecore_Exe_Data *exe)
{
efl_destructor(efl_super(obj, ECORE_EXE_CLASS));
_impl_ecore_exe_efl_object_destructor(obj, exe);
}
@ -239,9 +216,7 @@ ecore_exe_pid_get(const Ecore_Exe *obj)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return -1;
if (!efl_isa(obj, MY_CLASS)) return -1;
return exe->pid;
}
@ -250,9 +225,7 @@ ecore_exe_cmd_get(const Ecore_Exe *obj)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
const char *ret = NULL;
ecore_obj_exe_command_get(obj, &ret, NULL);
return ret;
}
@ -261,9 +234,7 @@ ecore_exe_data_get(const Ecore_Exe *obj)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return NULL;
if (!efl_isa(obj, MY_CLASS)) return NULL;
return exe->data;
}
@ -274,9 +245,7 @@ ecore_exe_data_set(Ecore_Exe *obj,
void *ret;
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return NULL;
if (!efl_isa(obj, MY_CLASS)) return NULL;
ret = exe->data;
exe->data = data;
return ret;
@ -287,9 +256,7 @@ ecore_exe_flags_get(const Ecore_Exe *obj)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return 0;
if (!efl_isa(obj, MY_CLASS)) return 0;
return exe->flags;
}
@ -309,15 +276,8 @@ EOLIAN static void
_ecore_exe_efl_control_suspend_set(Eo *obj EINA_UNUSED, Ecore_Exe_Data *exe, Eina_Bool suspend)
{
EINA_MAIN_LOOP_CHECK_RETURN;
if (suspend)
{
_impl_ecore_exe_pause(obj, exe);
}
else
{
_impl_ecore_exe_continue(obj, exe);
}
if (suspend) _impl_ecore_exe_pause(obj, exe);
else _impl_ecore_exe_continue(obj, exe);
}
EAPI void
@ -325,9 +285,7 @@ ecore_exe_interrupt(Ecore_Exe *obj)
{
EINA_MAIN_LOOP_CHECK_RETURN;
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return;
if (!efl_isa(obj, MY_CLASS)) return;
_impl_ecore_exe_interrupt(obj, exe);
}
@ -336,9 +294,7 @@ ecore_exe_quit(Ecore_Exe *obj)
{
EINA_MAIN_LOOP_CHECK_RETURN;
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return;
if (!efl_isa(obj, MY_CLASS)) return;
_impl_ecore_exe_quit(obj, exe);
}
@ -347,9 +303,7 @@ ecore_exe_terminate(Ecore_Exe *obj)
{
EINA_MAIN_LOOP_CHECK_RETURN;
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return;
if (!efl_isa(obj, MY_CLASS)) return;
_impl_ecore_exe_terminate(obj, exe);
}
@ -358,9 +312,7 @@ ecore_exe_kill(Ecore_Exe *obj)
{
EINA_MAIN_LOOP_CHECK_RETURN;
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return;
if (!efl_isa(obj, MY_CLASS)) return;
_impl_ecore_exe_kill(obj, exe);
}
@ -370,9 +322,7 @@ ecore_exe_signal(Ecore_Exe *obj,
{
EINA_MAIN_LOOP_CHECK_RETURN;
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return;
if (!efl_isa(obj, MY_CLASS)) return;
_impl_ecore_exe_signal(obj, exe, num);
}
@ -381,9 +331,7 @@ ecore_exe_hup(Ecore_Exe *obj)
{
EINA_MAIN_LOOP_CHECK_RETURN;
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (!efl_isa(obj, MY_CLASS))
return;
if (!efl_isa(obj, MY_CLASS)) return;
_impl_ecore_exe_hup(obj, exe);
}
@ -401,7 +349,9 @@ _ecore_exe_shutdown(void)
{
Ecore_Exe *exe = NULL;
Eina_List *l1, *l2;
EINA_LIST_FOREACH_SAFE(_ecore_exe_exes, l1, l2, exe)
Efl_Loop_Data *loop = EFL_LOOP_DATA;
EINA_LIST_FOREACH_SAFE(loop->exes, l1, l2, exe)
ecore_exe_free(exe);
ecore_event_type_flush(ECORE_EXE_EVENT_ADD,
@ -415,22 +365,20 @@ _ecore_exe_find(pid_t pid)
{
Eina_List *itr;
Ecore_Exe *obj;
Efl_Loop_Data *loop = EFL_LOOP_DATA;
EINA_LIST_FOREACH(_ecore_exe_exes, itr, obj)
{
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (exe->pid == pid)
return obj;
}
EINA_LIST_FOREACH(loop->exes, itr, obj)
{
Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
if (exe->pid == pid) return obj;
}
return NULL;
}
void *
_ecore_exe_event_del_new(void)
{
Ecore_Exe_Event_Del *e;
e = calloc(1, sizeof(Ecore_Exe_Event_Del));
Ecore_Exe_Event_Del *e = calloc(1, sizeof(Ecore_Exe_Event_Del));
return e;
}
@ -438,11 +386,8 @@ void
_ecore_exe_event_del_free(void *data EINA_UNUSED,
void *ev)
{
Ecore_Exe_Event_Del *e;
e = ev;
if (e->exe)
ecore_exe_free(e->exe);
Ecore_Exe_Event_Del *e = ev;
if (e->exe) ecore_exe_free(e->exe);
free(e);
}
@ -450,18 +395,14 @@ void
_ecore_exe_event_exe_data_free(void *data EINA_UNUSED,
void *ev)
{
Ecore_Exe_Event_Data *e;
e = ev;
Ecore_Exe_Event_Data *e = ev;
ecore_exe_event_data_free(e);
}
Ecore_Exe_Event_Add *
_ecore_exe_event_add_new(void)
{
Ecore_Exe_Event_Add *e;
e = calloc(1, sizeof(Ecore_Exe_Event_Add));
Ecore_Exe_Event_Add *e = calloc(1, sizeof(Ecore_Exe_Event_Add));
return e;
}
@ -469,9 +410,7 @@ void
_ecore_exe_event_add_free(void *data EINA_UNUSED,
void *ev)
{
Ecore_Exe_Event_Add *e;
e = ev;
Ecore_Exe_Event_Add *e = ev;
free(e);
}

File diff suppressed because it is too large Load Diff

View File

@ -68,10 +68,9 @@ typedef enum
struct _Ecore_Exe_Data
{
pid_t pid;
void *data;
char *tag, *cmd;
Ecore_Exe_Flags flags;
Eo *loop;
#ifdef _WIN32
HANDLE process;
@ -124,10 +123,11 @@ struct _Ecore_Exe_Data
int start_bytes, end_bytes, start_lines, end_lines; /* Number of bytes/lines to auto pipe at start/end of stdout/stderr. */
Ecore_Timer *doomsday_clock; /* The Timer of Death. Muahahahaha. */
void *doomsday_clock_dead; /* data for the doomsday clock */
#endif
Ecore_Exe_Cb pre_free_cb;
pid_t pid;
Ecore_Exe_Flags flags;
Eina_Bool close_stdin : 1;
};
@ -137,7 +137,6 @@ EAPI extern int ECORE_EXE_EVENT_ADD;
EAPI extern int ECORE_EXE_EVENT_DEL;
EAPI extern int ECORE_EXE_EVENT_DATA;
EAPI extern int ECORE_EXE_EVENT_ERROR;
extern Eina_List *_ecore_exe_exes;
Ecore_Exe *_ecore_exe_find(pid_t pid);
void *_ecore_exe_event_del_new(void);

View File

@ -528,7 +528,9 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
goto error;
}
_ecore_exe_exes = eina_list_append(_ecore_exe_exes, obj);
exe->loop = efl_provider_find(obj, EFL_LOOP_CLASS);
Efl_Loop_Data *loop = efl_data_scope_get(exe->loop, EFL_LOOP_CLASS);
if (loop) loop->exes = eina_list_append(loop->exes, obj);
e = calloc(1, sizeof(Ecore_Exe_Event_Add));
if (!e) goto error;
@ -711,7 +713,8 @@ _impl_ecore_exe_efl_object_destructor(Eo *obj, Ecore_Exe_Data *exe)
IF_FREE(exe->cmd);
_ecore_exe_exes = eina_list_remove(_ecore_exe_exes, obj);
Efl_Loop_Data *loop = efl_data_scope_get(exe->loop, EFL_LOOP_CLASS);
if (loop) loop->exes = eina_list_remove(loop->exes, obj);
IF_FREE(exe->tag);
}

View File

@ -35,7 +35,7 @@ _ecore_job_init(void)
void
_ecore_job_shutdown(void)
{
_ecore_event_handler_del(_ecore_job_handler);
ecore_event_handler_del(_ecore_job_handler);
_ecore_job_handler = NULL;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,96 @@
//////////////////////////////////////////////////////////////////////////
#if defined(HAVE_SYS_EPOLL_H)
# define HAVE_EPOLL 1
# include <sys/epoll.h>
#else
# define HAVE_EPOLL 0
# define EPOLLIN 1
# define EPOLLPRI 2
# define EPOLLOUT 4
# define EPOLLERR 8
# define EPOLL_CTL_ADD 1
# define EPOLL_CTL_DEL 2
# define EPOLL_CTL_MOD 3
typedef union epoll_data
{
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event
{
uint32_t events;
epoll_data_t data;
};
static inline int
epoll_create(int size EINA_UNUSED)
{
return -1;
}
static inline int
epoll_wait(int epfd EINA_UNUSED,
struct epoll_event *events EINA_UNUSED,
int maxevents EINA_UNUSED,
int timeout EINA_UNUSED)
{
return -1;
}
static inline int
epoll_ctl(int epfd EINA_UNUSED,
int op EINA_UNUSED,
int fd EINA_UNUSED,
struct epoll_event *event EINA_UNUSED)
{
return -1;
}
#endif
//////////////////////////////////////////////////////////////////////////
#ifdef HAVE_SYS_TIMERFD_H
# include <sys/timerfd.h>
#else
/* fallback code if we don't have real timerfd - reduces number of ifdefs */
# ifndef CLOCK_MONOTONIC
# define CLOCK_MONOTONIC 0 /* bogus value */
# endif
# ifndef TFD_NONBLOCK
# define TFD_NONBLOCK 0 /* bogus value */
# endif
#endif /* HAVE_SYS_TIMERFD_H */
#ifndef TFD_TIMER_ABSTIME
# define TFD_TIMER_ABSTIME (1 << 0)
#endif
#ifndef TFD_TIMER_CANCEL_ON_SET
# define TFD_TIMER_CANCEL_ON_SET (1 << 1)
#endif
#ifndef TIME_T_MAX
# define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
#endif
#ifndef HAVE_TIMERFD_CREATE
static inline int
timerfd_create(int clockid EINA_UNUSED,
int flags EINA_UNUSED)
{
return -1;
}
static inline int
timerfd_settime(int fd EINA_UNUSED,
int flags EINA_UNUSED,
const struct itimerspec *new_value EINA_UNUSED,
struct itimerspec *old_value EINA_UNUSED)
{
return -1;
}
#endif /* HAVE_TIMERFD_CREATE */

View File

@ -0,0 +1,88 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/time.h>
#include "Ecore.h"
#include "ecore_private.h"
#include "lib/ecore/ecore_main_common.h"
#ifdef HAVE_SYS_TIMERFD_H
static Eo *realtime_obj = NULL;
static void
_cb_read(void *data EINA_UNUSED, const Efl_Event *event)
{
Eo *loop = efl_provider_find(event->object, EFL_LOOP_CLASS);
int fd = efl_loop_handler_fd_get(event->object);
char buf[8];
if (read(fd, buf, sizeof(buf)) >= 0) return;
DBG("system clock changed");
// XXX: ecore event needs to be eo loop api's
ecore_event_add(ECORE_EVENT_SYSTEM_TIMEDATE_CHANGED, NULL, NULL, NULL);
_ecore_main_timechanges_stop(loop);
_ecore_main_timechanges_start(loop);
}
static void
_cb_del(void *data EINA_UNUSED, const Efl_Event *event)
{
int fd = efl_loop_handler_fd_get(event->object);
if (event->object == realtime_obj) realtime_obj = NULL;
close(fd);
}
EFL_CALLBACKS_ARRAY_DEFINE(_event_watch,
{ EFL_LOOP_HANDLER_EVENT_READ, _cb_read },
{ EFL_EVENT_DEL, _cb_del });
#endif
void
_ecore_main_timechanges_start(Eo *obj)
{
#ifdef HAVE_SYS_TIMERFD_H
struct itimerspec its;
int fd;
if (realtime_obj) return;
fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC);
if (fd < 0) return;
memset(&its, 0, sizeof(its));
its.it_value.tv_sec = TIME_T_MAX; // end of time - 0xf
if (timerfd_settime(fd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
&its, NULL) < 0)
{
WRN("Couldn't arm timerfd to detect clock changes: %s", strerror(errno));
close(fd);
return;
}
realtime_obj =
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
efl_loop_handler_fd_set(efl_added, fd),
efl_loop_handler_active_set(efl_added, ECORE_FD_READ),
efl_event_callback_array_add(efl_added, _event_watch(), NULL));
#endif
}
void
_ecore_main_timechanges_stop(Eo *obj EINA_UNUSED)
{
#ifdef HAVE_SYS_TIMERFD_H
if (!realtime_obj) return;
efl_del(realtime_obj);
realtime_obj = NULL;
#endif
}

View File

@ -56,16 +56,12 @@
#define PIPE_FD_INVALID -1
#ifdef _WIN32
# include <winsock2.h>
# define pipe_write(fd, buffer, size) send((fd), (char *)(buffer), size, 0)
# define pipe_read(fd, buffer, size) recv((fd), (char *)(buffer), size, 0)
# define pipe_close(fd) closesocket(fd)
# define PIPE_FD_ERROR SOCKET_ERROR
#else
# ifdef HAVE_SYS_EPOLL_H
# include <sys/epoll.h>
# endif /* HAVE_SYS_EPOLL_H */
@ -74,23 +70,21 @@
# endif
# include <unistd.h>
# include <fcntl.h>
# define pipe_write(fd, buffer, size) write((fd), buffer, size)
# define pipe_read(fd, buffer, size) read((fd), buffer, size)
# define pipe_close(fd) close(fd)
# define PIPE_FD_ERROR -1
#endif /* ! _WIN32 */
#include "Ecore.h"
#include "ecore_private.h"
/* How of then we should retry to write to the pipe */
// How of then we should retry to write to the pipe
#define ECORE_PIPE_WRITE_RETRY 6
struct _Ecore_Pipe
{
ECORE_MAGIC;
ECORE_MAGIC;
int fd_read;
int fd_write;
Ecore_Fd_Handler *fd_handler;
@ -116,11 +110,7 @@ EAPI Ecore_Pipe *
ecore_pipe_add(Ecore_Pipe_Cb handler,
const void *data)
{
Ecore_Pipe *p;
p = _ecore_pipe_add(handler, data);
return p;
return _ecore_pipe_add(handler, data);
}
EAPI void *
@ -138,11 +128,11 @@ ecore_pipe_read_close(Ecore_Pipe *p)
if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
{
ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_read_close");
return ;
return;
}
if (p->fd_handler)
{
_ecore_main_fd_handler_del(p->fd_handler);
_ecore_main_fd_handler_del(ML_OBJ, ML_DAT, p->fd_handler);
p->fd_handler = NULL;
}
if (p->fd_read != PIPE_FD_INVALID)
@ -166,11 +156,11 @@ ecore_pipe_freeze(Ecore_Pipe *p)
if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
{
ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_read_freeze");
return ;
return;
}
if (p->fd_handler)
{
_ecore_main_fd_handler_del(p->fd_handler);
_ecore_main_fd_handler_del(ML_OBJ, ML_DAT, p->fd_handler);
p->fd_handler = NULL;
}
}
@ -182,16 +172,12 @@ ecore_pipe_thaw(Ecore_Pipe *p)
if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
{
ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_read_thaw");
return ;
}
if (!p->fd_handler && p->fd_read != PIPE_FD_INVALID)
{
p->fd_handler = ecore_main_fd_handler_add(p->fd_read,
ECORE_FD_READ,
_ecore_pipe_read,
p,
NULL, NULL);
return;
}
if ((!p->fd_handler) && (p->fd_read != PIPE_FD_INVALID))
p->fd_handler = ecore_main_fd_handler_add(p->fd_read, ECORE_FD_READ,
_ecore_pipe_read, p,
NULL, NULL);
}
EAPI int
@ -208,7 +194,7 @@ ecore_pipe_write_close(Ecore_Pipe *p)
if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
{
ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_write_close");
return ;
return;
}
if (p->fd_write != PIPE_FD_INVALID)
{
@ -244,8 +230,7 @@ ecore_pipe_write(Ecore_Pipe *p,
if (p->fd_write == PIPE_FD_INVALID) goto out;
/* First write the len into the pipe */
do
do // First write the len into the pipe
{
ret = pipe_write(p->fd_write, &nbytes, sizeof(nbytes));
if (ret == sizeof(nbytes))
@ -255,19 +240,19 @@ ecore_pipe_write(Ecore_Pipe *p,
}
else if (ret > 0)
{
/* XXX What should we do here? */
ERR("The length of the data was not written complete"
" to the pipe");
goto out;
// XXX What should we do here?
ERR("The length of the data was not written complete"
" to the pipe");
goto out;
}
else if (ret == PIPE_FD_ERROR && errno == EPIPE)
else if ((ret == PIPE_FD_ERROR) && (errno == EPIPE))
{
pipe_close(p->fd_write);
p->fd_write = PIPE_FD_INVALID;
goto out;
}
else if (ret == PIPE_FD_ERROR && errno == EINTR)
/* try it again */
else if ((ret == PIPE_FD_ERROR) && (errno == EINTR))
// try it again
;
else
{
@ -280,8 +265,7 @@ ecore_pipe_write(Ecore_Pipe *p,
if (retry != ECORE_PIPE_WRITE_RETRY) goto out;
/* and now pass the data to the pipe */
do
do // and now pass the data to the pipe
{
ret = pipe_write(p->fd_write,
((unsigned char *)buffer) + already_written,
@ -289,22 +273,22 @@ ecore_pipe_write(Ecore_Pipe *p,
if (ret == (ssize_t)(nbytes - already_written))
{
ok = EINA_TRUE;
goto out;
ok = EINA_TRUE;
goto out;
}
else if (ret >= 0)
{
already_written -= ret;
continue;
}
else if (ret == PIPE_FD_ERROR && errno == EPIPE)
else if ((ret == PIPE_FD_ERROR) && (errno == EPIPE))
{
pipe_close(p->fd_write);
p->fd_write = PIPE_FD_INVALID;
goto out;
}
else if (ret == PIPE_FD_ERROR && errno == EINTR)
/* try it again */
else if ((ret == PIPE_FD_ERROR) && (errno == EINTR))
// try it again
;
else
{
@ -336,8 +320,7 @@ ecore_pipe_full_add(Ecore_Pipe_Cb handler,
p = ecore_pipe_calloc(1);
if (!p) return NULL;
if (fd_read == -1 &&
fd_write == -1)
if ((fd_read == -1) && (fd_write == -1))
{
if (pipe(fds))
{
@ -349,8 +332,8 @@ ecore_pipe_full_add(Ecore_Pipe_Cb handler,
}
else
{
fd_read = fd_read == -1 ? PIPE_FD_INVALID : fd_read;
fd_write = fd_write == -1 ? PIPE_FD_INVALID : fd_write;
fd_read = (fd_read == -1) ? PIPE_FD_INVALID : fd_read;
fd_write = (fd_write == -1) ? PIPE_FD_INVALID : fd_write;
}
ECORE_MAGIC_SET(p, ECORE_MAGIC_PIPE);
@ -359,10 +342,8 @@ ecore_pipe_full_add(Ecore_Pipe_Cb handler,
p->handler = handler;
p->data = data;
if (!read_survive_fork)
eina_file_close_on_exec(fd_read, EINA_TRUE);
if (!write_survive_fork)
eina_file_close_on_exec(fd_write, EINA_TRUE);
if (!read_survive_fork) eina_file_close_on_exec(fd_read, EINA_TRUE);
if (!write_survive_fork) eina_file_close_on_exec(fd_write, EINA_TRUE);
#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_SYS_TIMERFD_H)
struct epoll_event pollev = { 0 };
@ -381,23 +362,17 @@ ecore_pipe_full_add(Ecore_Pipe_Cb handler,
if (fcntl(p->fd_read, F_SETFL, O_NONBLOCK) < 0)
ERR("can't set pipe to NONBLOCK");
p->fd_handler = ecore_main_fd_handler_add(p->fd_read,
ECORE_FD_READ,
_ecore_pipe_read,
p,
NULL, NULL);
p->fd_handler = ecore_main_fd_handler_add(p->fd_read, ECORE_FD_READ,
_ecore_pipe_read, p, NULL, NULL);
return p;
}
/* Private functions */
// Private functions
Ecore_Pipe *
_ecore_pipe_add(Ecore_Pipe_Cb handler,
const void *data)
{
return ecore_pipe_full_add(handler, data,
-1, -1,
EINA_FALSE, EINA_FALSE);
return ecore_pipe_full_add(handler, data, -1, -1, EINA_FALSE, EINA_FALSE);
}
void *
@ -420,7 +395,8 @@ _ecore_pipe_del(Ecore_Pipe *p)
#endif
p->delete_me = EINA_TRUE;
if (p->handling > 0) return (void *)p->data;
if (p->fd_handler) _ecore_main_fd_handler_del(p->fd_handler);
if (p->fd_handler) _ecore_main_fd_handler_del(ML_OBJ, ML_DAT,
p->fd_handler);
if (p->fd_read != PIPE_FD_INVALID) pipe_close(p->fd_read);
if (p->fd_write != PIPE_FD_INVALID) pipe_close(p->fd_write);
p->fd_handler = NULL;
@ -435,10 +411,7 @@ static void
_ecore_pipe_unhandle(Ecore_Pipe *p)
{
p->handling--;
if (p->delete_me)
{
_ecore_pipe_del(p);
}
if (p->delete_me) _ecore_pipe_del(p);
}
#if ! defined(HAVE_SYS_EPOLL_H) || ! defined(HAVE_SYS_TIMERFD_H)
@ -455,23 +428,21 @@ _ecore_pipe_wait(Ecore_Pipe *p,
int total = 0;
EINA_MAIN_LOOP_CHECK_RETURN_VAL(-1);
if (p->fd_read == PIPE_FD_INVALID)
return -1;
if (p->fd_read == PIPE_FD_INVALID) return -1;
FD_ZERO(&rset);
FD_ZERO(&wset);
FD_ZERO(&exset);
FD_SET(p->fd_read, &rset);
if (wait >= 0.0)
end = ecore_time_get() + wait;
if (wait >= 0.0) end = ecore_time_get() + wait;
timeout = wait;
while (message_count > 0 && (timeout > 0.0 || wait <= 0.0))
while ((message_count > 0) && ((timeout > 0.0) || (wait <= 0.0)))
{
if (wait >= 0.0)
{
/* finite() tests for NaN, too big, too small, and infinity. */
// finite() tests for NaN, too big, too small, and infinity.
if ((!ECORE_FINITE(timeout)) || (EINA_DBL_EQ(timeout, 0.0)))
{
tv.tv_sec = 0;
@ -490,10 +461,7 @@ _ecore_pipe_wait(Ecore_Pipe *p,
}
t = &tv;
}
else
{
t = NULL;
}
else t = NULL;
ret = main_loop_select(p->fd_read + 1, &rset, &wset, &exset, t);
@ -506,10 +474,7 @@ _ecore_pipe_wait(Ecore_Pipe *p,
p->message = 0;
_ecore_pipe_unhandle(p);
}
else if (ret == 0)
{
break;
}
else if (ret == 0) break;
else if (errno != EINTR)
{
if (p->fd_read != PIPE_FD_INVALID)
@ -520,8 +485,7 @@ _ecore_pipe_wait(Ecore_Pipe *p,
break;
}
if (wait >= 0.0)
timeout = end - ecore_time_get();
if (wait >= 0.0) timeout = end - ecore_time_get();
}
return total;
@ -538,18 +502,17 @@ _ecore_pipe_wait(Ecore_Pipe *p,
double timeout;
int ret;
int total = 0;
int time_exit=-1;
int time_exit = -1;
Eina_Bool fd_read_found;
Eina_Bool fd_timer_found;
struct itimerspec tspec_new;
EINA_MAIN_LOOP_CHECK_RETURN_VAL(-1);
if (p->fd_read == PIPE_FD_INVALID)
return -1;
if (p->fd_read == PIPE_FD_INVALID) return -1;
timeout = wait;
int sec, usec;
if ( wait >= 0.0)
if (wait >= 0.0)
{
if ((!ECORE_FINITE(timeout)) || (EINA_DBL_EQ(timeout, 0.0)))
{
@ -571,45 +534,45 @@ _ecore_pipe_wait(Ecore_Pipe *p,
tspec_new.it_interval.tv_sec = 0;
tspec_new.it_interval.tv_nsec = 0;
timerfd_settime(p->timerfd, 0, &tspec_new, NULL);
}
}
}
while ((ret = epoll_wait(p->pollfd, pollincoming, 2, time_exit)) > 0)
{
fd_read_found = EINA_FALSE;
fd_timer_found = EINA_FALSE;
fd_read_found = EINA_FALSE;
fd_timer_found = EINA_FALSE;
for (int i = 0; i < ret;i++)
{
if ((&p->fd_read == pollincoming[i].data.ptr))
fd_read_found = EINA_TRUE;
if ((&p->timerfd == pollincoming[i].data.ptr))
fd_timer_found = EINA_TRUE;
}
for (int i = 0; i < ret;i++)
{
if ((&p->fd_read == pollincoming[i].data.ptr))
fd_read_found = EINA_TRUE;
if ((&p->timerfd == pollincoming[i].data.ptr))
fd_timer_found = EINA_TRUE;
}
p->handling++;
if (fd_read_found)
{
_ecore_pipe_read(p, NULL);
message_count -= p->message;
total += p->message;
p->message = 0;
if (message_count <= 0)
{
_ecore_pipe_unhandle(p);
break;
}
}
p->handling++;
if (fd_read_found)
{
_ecore_pipe_read(p, NULL);
message_count -= p->message;
total += p->message;
p->message = 0;
if (message_count <= 0)
{
_ecore_pipe_unhandle(p);
break;
}
}
if ((fd_timer_found) && (p->timerfd != PIPE_FD_INVALID))
{
if (pipe_read(p->timerfd, &timerfdbuf, sizeof(timerfdbuf))
< (int)sizeof(int64_t))
WRN("Could not read timerfd data");
_ecore_pipe_unhandle(p);
break;
}
_ecore_pipe_unhandle(p);
if ((fd_timer_found) && (p->timerfd != PIPE_FD_INVALID))
{
if (pipe_read(p->timerfd, &timerfdbuf, sizeof(timerfdbuf)) <
(int)sizeof(int64_t))
WRN("Could not read timerfd data");
_ecore_pipe_unhandle(p);
break;
}
_ecore_pipe_unhandle(p);
}
if (ret < 0)
{
@ -623,7 +586,6 @@ _ecore_pipe_wait(Ecore_Pipe *p,
WRN("The call was interrupted by a signal handler before any of the requested epoll_event "
"occurred or the timeout expired; see signal(7).");
}
return total;
}
@ -641,10 +603,7 @@ _ecore_pipe_handler_call(Ecore_Pipe *p,
p->len = 0;
p->message++;
if (!p->delete_me)
{
p->handler(data, buf, len);
}
if (!p->delete_me) p->handler(data, buf, len);
// free p->passed_data
free(buf);
@ -662,64 +621,63 @@ _ecore_pipe_read(void *data,
{
ssize_t ret;
/* if we already have read some data we don't need to read the len
* but to finish the already started job
*/
// if we already have read some data we don't need to read the len
// but to finish the already started job
if (p->len == 0)
{
/* read the len of the passed data */
ret = pipe_read(p->fd_read, &p->len, sizeof(p->len));
// read the len of the passed data
ret = pipe_read(p->fd_read, &p->len, sizeof(p->len));
/* catch the non error case first */
/* read amount ok - nothing more to do */
if (ret == sizeof(p->len))
;
else if (ret > 0)
{
/* we got more data than we asked for - definite error */
ERR("Only read %i bytes from the pipe, although"
" we need to read %i bytes.",
(int)ret, (int)sizeof(p->len));
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_CANCEL;
}
else if (ret == 0)
{
/* we got no data */
if (i == 0)
{
/* no data on first try through means an error */
_ecore_pipe_handler_call(p, NULL, 0);
pipe_close(p->fd_read);
p->fd_read = PIPE_FD_INVALID;
p->fd_handler = NULL;
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_CANCEL;
}
else
{
/* no data after first loop try is ok */
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_RENEW;
}
}
// catch the non error case first
// read amount ok - nothing more to do
if (ret == sizeof(p->len))
;
else if (ret > 0)
{
// we got more data than we asked for - definite error
ERR("Only read %i bytes from the pipe, although"
" we need to read %i bytes.",
(int)ret, (int)sizeof(p->len));
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_CANCEL;
}
else if (ret == 0)
{
// we got no data
if (i == 0)
{
// no data on first try through means an error
_ecore_pipe_handler_call(p, NULL, 0);
pipe_close(p->fd_read);
p->fd_read = PIPE_FD_INVALID;
p->fd_handler = NULL;
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_CANCEL;
}
else
{
// no data after first loop try is ok
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_RENEW;
}
}
#ifndef _WIN32
else if ((ret == PIPE_FD_ERROR) &&
((errno == EINTR) || (errno == EAGAIN)))
else if ((ret == PIPE_FD_ERROR) &&
((errno == EINTR) || (errno == EAGAIN)))
{
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_RENEW;
}
else
{
ERR("An unhandled error (ret: %i errno: %i [%s])"
"occurred while reading from the pipe the length",
(int)ret, errno, strerror(errno));
_ecore_pipe_unhandle(p);
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_RENEW;
}
else
{
ERR("An unhandled error (ret: %i errno: %i [%s])"
"occurred while reading from the pipe the length",
(int)ret, errno, strerror(errno));
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_RENEW;
}
#else
else /* ret == PIPE_FD_ERROR is the only other case on Windows */
else // ret == PIPE_FD_ERROR is the only other case on Windows
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
@ -733,10 +691,9 @@ _ecore_pipe_read(void *data,
}
#endif
}
/* if somehow we got less than or equal to 0 we got an errnoneous
* messages so call callback with null and len we got. this case should
* never happen */
// if somehow we got less than or equal to 0 we got an errnoneous
// messages so call callback with null and len we got. this case should
// never happen
if (p->len == 0)
{
_ecore_pipe_handler_call(p, NULL, 0);
@ -744,15 +701,15 @@ _ecore_pipe_read(void *data,
return ECORE_CALLBACK_RENEW;
}
/* we dont have a buffer to hold the data, so alloc it */
// we dont have a buffer to hold the data, so alloc it
if (!p->passed_data)
{
p->passed_data = malloc(p->len);
/* alloc failed - error case */
// alloc failed - error case
if (!p->passed_data)
{
_ecore_pipe_handler_call(p, NULL, 0);
/* close the pipe */
// close the pipe
pipe_close(p->fd_read);
p->fd_read = PIPE_FD_INVALID;
p->fd_handler = NULL;
@ -761,27 +718,27 @@ _ecore_pipe_read(void *data,
}
}
/* and read the passed data */
// and read the passed data
ret = pipe_read(p->fd_read,
((unsigned char *)p->passed_data) + p->already_read,
p->len - p->already_read);
/* catch the non error case first */
/* if we read enough data to finish the message/buffer */
// catch the non error case first
// if we read enough data to finish the message/buffer
if (ret == (ssize_t)(p->len - p->already_read))
_ecore_pipe_handler_call(p, p->passed_data, p->len);
else if (ret > 0)
{
/* more data left to read */
p->already_read += (unsigned int) ret;
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_RENEW;
// more data left to read
p->already_read += (unsigned int)ret;
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_RENEW;
}
else if (ret == 0)
{
/* 0 bytes to read - could be more to read next select wake up */
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_RENEW;
// 0 bytes to read - could be more to read next select wake up
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_RENEW;
}
#ifndef _WIN32
else if ((ret == PIPE_FD_ERROR) &&
@ -799,7 +756,7 @@ _ecore_pipe_read(void *data,
return ECORE_CALLBACK_RENEW;
}
#else
else /* ret == PIPE_FD_ERROR is the only other case on Windows */
else // ret == PIPE_FD_ERROR is the only other case on Windows
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
@ -810,8 +767,7 @@ _ecore_pipe_read(void *data,
_ecore_pipe_unhandle(p);
return ECORE_CALLBACK_CANCEL;
}
else
break;
else break;
}
#endif
}

View File

@ -83,22 +83,84 @@ 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_Data Efl_Loop_Data;
typedef struct _Message_Handler Message_Handler;
typedef struct _Message Message;
struct _Message_Handler
{
Eo *handler;
const Eo *klass;
};
struct _Message
{
EINA_INLIST;
Eo *handler;
Eo *message;
Eina_Bool delete_me;
};
struct _Efl_Loop_Data
{
Eina_Hash *providers;
double loop_time;
Eina_Hash *providers;
Ecore_Timer *poll_high;
Ecore_Timer *poll_medium;
Ecore_Timer *poll_low;
Ecore_Timer *poll_high;
Ecore_Timer *poll_medium;
Ecore_Timer *poll_low;
int idlers;
Eina_List *exes; // only used in main loop (for now?)
Eina_List *fd_handlers_obj;
Ecore_Fd_Handler *fd_handlers;
Eina_List *fd_handlers_with_prep;
Eina_List *file_fd_handlers;
Eina_List *fd_handlers_with_buffer;
Eina_List *fd_handlers_to_delete;
Ecore_Fd_Handler *fd_handlers_to_call;
Ecore_Fd_Handler *fd_handlers_to_call_current;
# ifdef _WIN32
Ecore_Win32_Handler *win32_handlers;
Ecore_Win32_Handler *win32_handler_current;
Eina_List *win32_handlers_to_delete;
# endif
Eina_List *pending_futures;
Eina_List *pending_promises;
Eina_Inarray *message_handlers;
Eina_Inlist *message_queue;
unsigned int message_walking;
unsigned int throttle;
int epoll_fd;
pid_t epoll_pid;
int timer_fd;
double last_check;
Eina_Inlist *timers;
Eina_Inlist *suspended;
Efl_Loop_Timer_Data *timer_current;
int timers_added;
Eina_Value exit_code;
int idlers;
int in_loop;
struct {
int high;
int medium;
int low;
int high;
int medium;
int low;
} pollers;
Eina_Bool do_quit;
};
#define EVAS_FRAME_QUEUING 1 /* for test */
@ -167,13 +229,11 @@ EAPI void _ecore_magic_fail(const void *d,
void _ecore_time_init(void);
void *_efl_loop_timer_del(Ecore_Timer *timer);
void _efl_loop_timer_shutdown(void);
void _efl_loop_timer_enable_new(void);
double _efl_loop_timer_next_get(void);
void _efl_loop_timer_expired_timers_call(double when);
int _efl_loop_timers_exists(void);
int _efl_loop_timer_expired_call(double when);
void _efl_loop_timer_enable_new(Eo *obj, Efl_Loop_Data *pd);
double _efl_loop_timer_next_get(Eo *obj, Efl_Loop_Data *pd);
void _efl_loop_timer_expired_timers_call(Eo *obj, Efl_Loop_Data *pd, double when);
int _efl_loop_timers_exists(Eo *obj, Efl_Loop_Data *pd);
int _efl_loop_timer_expired_call(Eo *obj, Efl_Loop_Data *pd, double when);
Ecore_Factorized_Idle *_ecore_factorized_idle_add(const Efl_Callback_Array_Item*desc,
Ecore_Task_Cb func,
@ -200,7 +260,6 @@ Ecore_Event *_ecore_event_add(int type,
Ecore_End_Cb func_free,
void *data);
void _ecore_event_call(void);
void *_ecore_event_handler_del(Ecore_Event_Handler *event_handler);
Ecore_Timer *_ecore_exe_doomsday_clock_get(Ecore_Exe *exe);
void _ecore_exe_doomsday_clock_set(Ecore_Exe *exe,
@ -219,16 +278,32 @@ int _ecore_pipe_wait(Ecore_Pipe *p,
double wait);
void *_ecore_pipe_del(Ecore_Pipe *p);
Ecore_Fd_Handler *
_ecore_main_fd_handler_add(int fd,
Ecore_Fd_Handler_Flags flags,
Ecore_Fd_Cb func,
const void *data,
Ecore_Fd_Cb buf_func,
const void *buf_data,
Eina_Bool is_file);
void *_ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler);
Ecore_Fd_Handler *_ecore_main_fd_handler_add(Eo *obj,
Efl_Loop_Data *pd,
Eo *handler,
int fd,
Ecore_Fd_Handler_Flags flags,
Ecore_Fd_Cb func,
const void *data,
Ecore_Fd_Cb buf_func,
const void *buf_data,
Eina_Bool is_file);
void *_ecore_main_fd_handler_del(Eo *obj,
Efl_Loop_Data *pd,
Ecore_Fd_Handler *fd_handler);
Ecore_Win32_Handler *
_ecore_main_win32_handler_add(Eo *obj,
Efl_Loop_Data *pd,
Eo *handler,
void *h,
Ecore_Win32_Handle_Cb func,
const void *data);
void *
_ecore_main_win32_handler_del(Eo *obj,
Efl_Loop_Data *pd,
Ecore_Win32_Handler *win32_handler);
void _ecore_main_content_clear(Efl_Loop_Data *pd);
void _ecore_main_shutdown(void);
#if defined (_WIN32) || defined (__lv2ppu__) || defined (HAVE_EXOTIC)
@ -236,18 +311,18 @@ static inline void _ecore_signal_shutdown(void) { }
static inline void _ecore_signal_init(void) { }
static inline void _ecore_signal_received_process(void) { }
static inline void _ecore_signal_received_process(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) { }
static inline int _ecore_signal_count_get(void) { return 0; }
static inline int _ecore_signal_count_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) { return 0; }
static inline void _ecore_signal_call(void) { }
static inline void _ecore_signal_call(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) { }
#else
void _ecore_signal_shutdown(void);
void _ecore_signal_init(void);
void _ecore_signal_received_process(void);
int _ecore_signal_count_get(void);
void _ecore_signal_call(void);
void _ecore_signal_received_process(Eo *obj, Efl_Loop_Data *pd);
int _ecore_signal_count_get(Eo *obj, Efl_Loop_Data *pd);
void _ecore_signal_call(Eo *obj, Efl_Loop_Data *pd);
#endif
void _ecore_exe_init(void);
@ -283,6 +358,11 @@ void _ecore_job_shutdown(void);
void _ecore_main_loop_init(void);
void _ecore_main_loop_shutdown(void);
void _ecore_main_loop_iterate(Eo *obj, Efl_Loop_Data *pd);
int _ecore_main_loop_iterate_may_block(Eo *obj, Efl_Loop_Data *pd, int may_block);
void _ecore_main_loop_begin(Eo *obj, Efl_Loop_Data *pd);
void _ecore_main_loop_quit(Eo *obj, Efl_Loop_Data *pd);
void _ecore_coroutine_init(void);
void _ecore_coroutine_shutdown(void);
@ -290,6 +370,17 @@ void _ecore_throttle(void);
void _ecore_main_call_flush(void);
void _ecore_main_timechanges_start(Eo *obj);
void _ecore_main_timechanges_stop(Eo *obj);
Eina_Bool _ecore_event_do_filter(void *handler_pd, Eo *msg_handler, Eo *msg);
void _ecore_event_filters_call(Eo *obj, Efl_Loop_Data *pd);
void _efl_loop_messages_filter(Eo *obj, Efl_Loop_Data *pd, void *handler_pd);
void _efl_loop_messages_call(Eo *obj, Efl_Loop_Data *pd, void *func, void *data);
void _efl_loop_message_send_info_set(Eo *obj, Eina_Inlist *node, Eo *loop, Efl_Loop_Data *loop_data);
void _efl_loop_message_unsend(Eo *obj);
static inline Eina_Bool
_ecore_call_task_cb(Ecore_Task_Cb func,
void *data)
@ -348,7 +439,6 @@ _ecore_call_fd_cb(Ecore_Fd_Cb func,
}
extern int _ecore_fps_debug;
extern double _ecore_time_loop_time;
extern Eina_Bool _ecore_glib_always_integrate;
extern Ecore_Select_Function main_loop_select;
extern int in_main_loop;
@ -362,9 +452,9 @@ void ecore_mempool_shutdown(void);
size_t _ecore_sizeof_##TYPE = sizeof (TYPE);
//GENERIC_ALLOC_FREE_HEADER(Ecore_Animator, ecore_animator);
GENERIC_ALLOC_FREE_HEADER(Ecore_Event_Handler, ecore_event_handler);
GENERIC_ALLOC_FREE_HEADER(Ecore_Event_Filter, ecore_event_filter);
GENERIC_ALLOC_FREE_HEADER(Ecore_Event, ecore_event);
//GENERIC_ALLOC_FREE_HEADER(Ecore_Event_Handler, ecore_event_handler);
//GENERIC_ALLOC_FREE_HEADER(Ecore_Event_Filter, ecore_event_filter);
//GENERIC_ALLOC_FREE_HEADER(Ecore_Event, ecore_event);
//GENERIC_ALLOC_FREE_HEADER(Ecore_Idle_Exiter, ecore_idle_exiter);
//GENERIC_ALLOC_FREE_HEADER(Ecore_Idle_Enterer, ecore_idle_enterer);
//GENERIC_ALLOC_FREE_HEADER(Ecore_Idler, ecore_idler);
@ -381,6 +471,11 @@ GENERIC_ALLOC_FREE_HEADER(Ecore_Win32_Handler, ecore_win32_handler);
#undef GENERIC_ALLOC_FREE_HEADER
extern Eo *_mainloop_singleton;
extern Efl_Loop_Data *_mainloop_singleton_data;
#define ML_OBJ _mainloop_singleton
#define ML_DAT _mainloop_singleton_data
//#define ML_DAT efl_data_scope_get(ML_OBJ, EFL_LOOP_CLASS)
extern Efl_Version _app_efl_version;
void ecore_loop_future_register(Efl_Loop *l, Efl_Future *f);
@ -392,6 +487,9 @@ void ecore_loop_promise_fulfill(Efl_Promise *p);
// access to direct input cb
#define ECORE_EVAS_INTERNAL
#define EFL_LOOP_DATA efl_data_scope_get(efl_loop_main_get(EFL_LOOP_CLASS), EFL_LOOP_CLASS)
#undef EAPI
#define EAPI

View File

@ -57,27 +57,27 @@ static Eina_Bool _ecore_signal_exe_exit_delay(void *data);
//#define MAXSIGQ 256 // 32k
#define MAXSIGQ 64 // 8k
static volatile sig_atomic_t sig_count = 0;
static volatile sig_atomic_t sig_count = 0;
static volatile sig_atomic_t sigchld_count = 0;
static volatile sig_atomic_t sigusr1_count = 0;
static volatile sig_atomic_t sigusr2_count = 0;
static volatile sig_atomic_t sighup_count = 0;
static volatile sig_atomic_t sighup_count = 0;
static volatile sig_atomic_t sigquit_count = 0;
static volatile sig_atomic_t sigint_count = 0;
static volatile sig_atomic_t sigint_count = 0;
static volatile sig_atomic_t sigterm_count = 0;
#ifdef SIGPWR
static volatile sig_atomic_t sigpwr_count = 0;
static volatile sig_atomic_t sigpwr_count = 0;
#endif
static volatile siginfo_t sigchld_info[MAXSIGQ];
static volatile siginfo_t sigusr1_info[MAXSIGQ];
static volatile siginfo_t sigusr2_info[MAXSIGQ];
static volatile siginfo_t sighup_info[MAXSIGQ];
static volatile siginfo_t sighup_info [MAXSIGQ];
static volatile siginfo_t sigquit_info[MAXSIGQ];
static volatile siginfo_t sigint_info[MAXSIGQ];
static volatile siginfo_t sigint_info [MAXSIGQ];
static volatile siginfo_t sigterm_info[MAXSIGQ];
#ifdef SIGPWR
static volatile siginfo_t sigpwr_info[MAXSIGQ];
static volatile siginfo_t sigpwr_info [MAXSIGQ];
#endif
#if defined(SIG_ATOMIC_MAX)
@ -108,22 +108,22 @@ _ecore_signal_shutdown(void)
_ecore_signal_callback_set(SIGCHLD, (Signal_Handler)SIG_DFL);
_ecore_signal_callback_set(SIGUSR1, (Signal_Handler)SIG_DFL);
_ecore_signal_callback_set(SIGUSR2, (Signal_Handler)SIG_DFL);
_ecore_signal_callback_set(SIGHUP, (Signal_Handler)SIG_DFL);
_ecore_signal_callback_set(SIGHUP, (Signal_Handler)SIG_DFL);
_ecore_signal_callback_set(SIGQUIT, (Signal_Handler)SIG_DFL);
_ecore_signal_callback_set(SIGINT, (Signal_Handler)SIG_DFL);
_ecore_signal_callback_set(SIGINT, (Signal_Handler)SIG_DFL);
_ecore_signal_callback_set(SIGTERM, (Signal_Handler)SIG_DFL);
#ifdef SIGPWR
_ecore_signal_callback_set(SIGPWR, (Signal_Handler)SIG_DFL);
sigpwr_count = 0;
_ecore_signal_callback_set(SIGPWR, (Signal_Handler)SIG_DFL);
sigpwr_count = 0;
#endif
sigchld_count = 0;
sigusr1_count = 0;
sigusr2_count = 0;
sighup_count = 0;
sighup_count = 0;
sigquit_count = 0;
sigint_count = 0;
sigint_count = 0;
sigterm_count = 0;
sig_count = 0;
sig_count = 0;
}
void
@ -134,36 +134,35 @@ _ecore_signal_init(void)
_ecore_signal_callback_set(SIGCHLD, _ecore_signal_callback_sigchld);
_ecore_signal_callback_set(SIGUSR1, _ecore_signal_callback_sigusr1);
_ecore_signal_callback_set(SIGUSR2, _ecore_signal_callback_sigusr2);
_ecore_signal_callback_set(SIGHUP, _ecore_signal_callback_sighup);
_ecore_signal_callback_set(SIGHUP, _ecore_signal_callback_sighup);
_ecore_signal_callback_set(SIGQUIT, _ecore_signal_callback_sigquit);
_ecore_signal_callback_set(SIGINT, _ecore_signal_callback_sigint);
_ecore_signal_callback_set(SIGINT, _ecore_signal_callback_sigint);
_ecore_signal_callback_set(SIGTERM, _ecore_signal_callback_sigterm);
#ifdef SIGPWR
_ecore_signal_callback_set(SIGPWR, _ecore_signal_callback_sigpwr);
_ecore_signal_callback_set(SIGPWR, _ecore_signal_callback_sigpwr);
#endif
}
void
_ecore_signal_received_process(void)
_ecore_signal_received_process(Eo *obj, Efl_Loop_Data *pd)
{
while (_ecore_signal_count_get()) _ecore_signal_call();
while (_ecore_signal_count_get(obj, pd)) _ecore_signal_call(obj, pd);
}
int
_ecore_signal_count_get(void)
_ecore_signal_count_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
{
return sig_count;
}
static void
_ecore_signal_generic_free(void *data EINA_UNUSED,
void *event)
_ecore_signal_generic_free(void *data EINA_UNUSED, void *event)
{
free(event);
}
void
_ecore_signal_call(void)
_ecore_signal_call(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
{
volatile sig_atomic_t n;
sigset_t oldset, newset;
@ -233,7 +232,9 @@ _ecore_signal_call(void)
if ((n < MAXSIGQ) && (sigchld_info[n].si_signo))
e->data = sigchld_info[n]; /* No need to clone this. */
if ((e->exe) && (ecore_exe_flags_get(e->exe) & (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR)))
if ((e->exe) &&
(ecore_exe_flags_get(e->exe) &
(ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR)))
{
/* We want to report the Last Words of the exe, so delay this event.
* This is twice as relevant for stderr.
@ -257,18 +258,18 @@ _ecore_signal_call(void)
* check to see for Last Words, and only delay if there are any.
* This has it's own set of problems.
*/
Ecore_Timer *doomsday_clock;
Ecore_Timer *doomsday_clock;
doomsday_clock = _ecore_exe_doomsday_clock_get(e->exe);
IF_FN_DEL(ecore_timer_del, doomsday_clock);
doomsday_clock = ecore_timer_add
(0.1, _ecore_signal_exe_exit_delay, e);
_ecore_exe_doomsday_clock_set(e->exe, doomsday_clock);
doomsday_clock = _ecore_exe_doomsday_clock_get(e->exe);
IF_FN_DEL(ecore_timer_del, doomsday_clock);
doomsday_clock = ecore_timer_add
(0.1, _ecore_signal_exe_exit_delay, e);
_ecore_exe_doomsday_clock_set(e->exe, doomsday_clock);
}
else
{
_ecore_event_add(ECORE_EXE_EVENT_DEL, e,
_ecore_exe_event_del_free, NULL);
ecore_event_add(ECORE_EXE_EVENT_DEL, e,
_ecore_exe_event_del_free, NULL);
}
}
}
@ -291,8 +292,8 @@ _ecore_signal_call(void)
if ((n < MAXSIGQ) && (sigusr1_info[n].si_signo))
e->data = sigusr1_info[n];
_ecore_event_add(ECORE_EVENT_SIGNAL_USER, e,
_ecore_signal_generic_free, NULL);
ecore_event_add(ECORE_EVENT_SIGNAL_USER, e,
_ecore_signal_generic_free, NULL);
}
sig_count--;
}
@ -313,8 +314,8 @@ _ecore_signal_call(void)
if ((n < MAXSIGQ) && (sigusr2_info[n].si_signo))
e->data = sigusr2_info[n];
_ecore_event_add(ECORE_EVENT_SIGNAL_USER, e,
_ecore_signal_generic_free, NULL);
ecore_event_add(ECORE_EVENT_SIGNAL_USER, e,
_ecore_signal_generic_free, NULL);
}
sig_count--;
}
@ -333,8 +334,8 @@ _ecore_signal_call(void)
if ((n < MAXSIGQ) && (sighup_info[n].si_signo))
e->data = sighup_info[n];
_ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e,
_ecore_signal_generic_free, NULL);
ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e,
_ecore_signal_generic_free, NULL);
}
sig_count--;
}
@ -355,8 +356,8 @@ _ecore_signal_call(void)
if ((n < MAXSIGQ) && (sigquit_info[n].si_signo))
e->data = sigquit_info[n];
_ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
_ecore_signal_generic_free, NULL);
ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
_ecore_signal_generic_free, NULL);
}
sig_count--;
}
@ -377,8 +378,8 @@ _ecore_signal_call(void)
if ((n < MAXSIGQ) && (sigint_info[n].si_signo))
e->data = sigint_info[n];
_ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
_ecore_signal_generic_free, NULL);
ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
_ecore_signal_generic_free, NULL);
}
sig_count--;
}
@ -399,8 +400,8 @@ _ecore_signal_call(void)
if ((n < MAXSIGQ) && (sigterm_info[n].si_signo))
e->data = sigterm_info[n];
_ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
_ecore_signal_generic_free, NULL);
ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
_ecore_signal_generic_free, NULL);
}
sig_count--;
}
@ -420,15 +421,15 @@ _ecore_signal_call(void)
if ((n < MAXSIGQ) && (sigpwr_info[n].si_signo))
e->data = sigpwr_info[n];
_ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e,
_ecore_signal_generic_free, NULL);
ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e,
_ecore_signal_generic_free, NULL);
}
sig_count--;
}
sigpwr_count = 0;
#endif
sig_count = 0;
sigprocmask(SIG_SETMASK, &oldset, NULL);
eina_evlog("-signals", NULL, 0.0, NULL);
}
@ -609,8 +610,8 @@ _ecore_signal_exe_exit_delay(void *data)
if (e)
{
_ecore_exe_doomsday_clock_set(e->exe, NULL);
_ecore_event_add(ECORE_EXE_EVENT_DEL, e,
_ecore_exe_event_del_free, NULL);
ecore_event_add(ECORE_EXE_EVENT_DEL, e,
_ecore_exe_event_del_free, NULL);
}
return ECORE_CALLBACK_CANCEL;
}

View File

@ -24,7 +24,6 @@ static Eina_Bool _ecore_time_got_clock_id = EINA_FALSE;
#elif defined(__APPLE__) && defined(__MACH__)
static double _ecore_time_clock_conversion = 1e-9;
#endif
double _ecore_time_loop_time = -1.0;
EAPI double
ecore_time_get(void)
@ -37,9 +36,9 @@ ecore_time_get(void)
if (EINA_UNLIKELY(clock_gettime(_ecore_time_clock_id, &t)))
{
CRI("Cannot get current time.");
/* Try to at least return the latest value retrieved*/
return _ecore_time_loop_time;
CRI("Cannot get current time");
// Try to at least return the latest value retrieved
return ecore_loop_time_get();
}
return (double)t.tv_sec + (((double)t.tv_nsec) / 1000000000.0);
@ -68,13 +67,13 @@ ecore_time_unix_get(void)
EAPI double
ecore_loop_time_get(void)
{
return _ecore_time_loop_time;
return efl_loop_time_get(ML_OBJ);
}
EAPI void
ecore_loop_time_set(double t)
{
_ecore_time_loop_time = t;
efl_loop_time_set(ML_OBJ, t);
}
/*-******************** Internal methods ********************************/
@ -86,7 +85,7 @@ ecore_loop_time_set(double t)
void
_ecore_time_init(void)
{
#if defined (HAVE_CLOCK_GETTIME) || defined (EXOTIC_PROVIDE_CLOCK_GETTIME)
#if defined(HAVE_CLOCK_GETTIME) || defined(EXOTIC_PROVIDE_CLOCK_GETTIME)
struct timespec t;
if (_ecore_time_got_clock_id) return;
@ -95,41 +94,32 @@ _ecore_time_init(void)
{
_ecore_time_clock_id = CLOCK_MONOTONIC;
_ecore_time_got_clock_id = EINA_TRUE;
DBG("using CLOCK_MONOTONIC.");
DBG("using CLOCK_MONOTONIC");
}
else if (!clock_gettime(CLOCK_REALTIME, &t))
{
/* may go backwards */
_ecore_time_clock_id = CLOCK_REALTIME;
_ecore_time_got_clock_id = EINA_TRUE;
WRN("CLOCK_MONOTONIC not available. Fallback to CLOCK_REALTIME.");
// may go backwards
_ecore_time_clock_id = CLOCK_REALTIME;
_ecore_time_got_clock_id = EINA_TRUE;
WRN("CLOCK_MONOTONIC not available. Fallback to CLOCK_REALTIME");
}
else
{
CRI("Cannot get a valid clock_gettime() clock id! "
"Fallback to unix time.");
}
CRI("Cannot get a valid clock_gettime() clock id! Fallback to unix time");
#else
# ifndef _WIN32
# if defined(__APPLE__) && defined(__MACH__)
mach_timebase_info_data_t info;
kern_return_t err = mach_timebase_info(&info);
if (err == 0)
{
_ecore_time_clock_conversion = 1e-9 * (double)info.numer / (double)info.denom;
}
  _ecore_time_clock_conversion = 1e-9 * (double)info.numer / (double)info.denom;
else
{
WRN("Unable to get timebase info. Fallback to nanoseconds.");
}
WRN("Unable to get timebase info. Fallback to nanoseconds");
# else
# warning "Your platform isn't supported yet"
CRI("Platform does not support clock_gettime. "
"Fallback to unix time.");
# warning "Your platform isn't supported yet"
CRI("Platform does not support clock_gettime. Fallback to unix time");
# endif
# endif
#endif
_ecore_time_loop_time = ecore_time_get();
ecore_loop_time_set(ecore_time_get());
}

View File

@ -13,45 +13,46 @@
#define MY_CLASS EFL_LOOP_TIMER_CLASS
#define MY_CLASS_NAME "Efl_Loop_Timer"
#define ECORE_TIMER_CHECK(obj) \
if (!efl_isa((obj), MY_CLASS)) \
return
#define ECORE_TIMER_CHECK(obj) if (!efl_isa((obj), MY_CLASS)) return
struct _Ecore_Timer_Legacy
{
Ecore_Task_Cb func;
const void *data;
Eina_Bool inside_call : 1;
Eina_Bool delete_me : 1;
};
struct _Efl_Loop_Timer_Data
{
EINA_INLIST;
Eo *object;
Eo *loop;
Efl_Loop_Data *loop_data;
double in;
double at;
double pending;
double in;
double at;
double pending;
int listening;
int listening;
unsigned char just_added : 1;
unsigned char frozen : 1;
unsigned char initialized : 1;
unsigned char noparent : 1;
Eina_Bool just_added : 1;
Eina_Bool frozen : 1;
Eina_Bool initialized : 1;
Eina_Bool noparent : 1;
Eina_Bool constructed : 1;
Eina_Bool finalized : 1;
};
typedef struct _Efl_Loop_Timer_Data Efl_Loop_Timer_Data;
typedef struct _Ecore_Timer_Legacy Ecore_Timer_Legacy;
static void _efl_loop_timer_util_delay(Efl_Loop_Timer_Data *timer,
double add);
static void _efl_loop_timer_util_instanciate(Efl_Loop_Timer_Data *timer);
static void _efl_loop_timer_set(Efl_Loop_Timer_Data *timer,
double at,
double in);
static void _efl_loop_timer_util_delay(Efl_Loop_Timer_Data *timer, double add);
static void _efl_loop_timer_util_instanciate(Efl_Loop_Data *loop, Efl_Loop_Timer_Data *timer);
static void _efl_loop_timer_set(Efl_Loop_Timer_Data *timer, double at, double in);
static Eina_Inlist *timers = NULL;
static Eina_Inlist *suspended = NULL;
static Efl_Loop_Timer_Data *timer_current = NULL;
static int timers_added = 0;
static double last_check = 0.0;
static double precision = 10.0 / 1000000.0;
EAPI double
@ -65,20 +66,15 @@ EAPI void
ecore_timer_precision_set(double value)
{
EINA_MAIN_LOOP_CHECK_RETURN;
if (value < 0.0)
{
ERR("Precision %f less than zero, ignored", value);
return ;
}
if (value < 0.0) value = 0.0;
precision = value;
}
static void
_check_timer_event_catcher_add(void *data, const Efl_Event *event)
{
const Efl_Callback_Array_Item *array = event->info;
Efl_Loop_Timer_Data *timer = data;
const Efl_Callback_Array_Item *array = event->info;
int i;
for (i = 0; array[i].desc != NULL; i++)
@ -86,7 +82,7 @@ _check_timer_event_catcher_add(void *data, const Efl_Event *event)
if (array[i].desc == EFL_LOOP_TIMER_EVENT_TICK)
{
if (timer->listening++ > 0) return;
_efl_loop_timer_util_instanciate(timer);
_efl_loop_timer_util_instanciate(timer->loop_data, timer);
// No need to walk more than once per array as you can not del
// a partial array
return;
@ -97,8 +93,8 @@ _check_timer_event_catcher_add(void *data, const Efl_Event *event)
static void
_check_timer_event_catcher_del(void *data, const Efl_Event *event)
{
const Efl_Callback_Array_Item *array = event->info;
Efl_Loop_Timer_Data *timer = data;
const Efl_Callback_Array_Item *array = event->info;
int i;
for (i = 0; array[i].desc != NULL; i++)
@ -106,7 +102,7 @@ _check_timer_event_catcher_del(void *data, const Efl_Event *event)
if (array[i].desc == EFL_LOOP_TIMER_EVENT_TICK)
{
if ((--timer->listening) > 0) return;
_efl_loop_timer_util_instanciate(timer);
_efl_loop_timer_util_instanciate(timer->loop_data, timer);
return;
}
}
@ -120,59 +116,38 @@ EOLIAN static Eo *
_efl_loop_timer_efl_object_constructor(Eo *obj, Efl_Loop_Timer_Data *timer)
{
efl_constructor(efl_super(obj, MY_CLASS));
efl_event_callback_array_add(obj, timer_watch(), timer);
efl_wref_add(obj, &timer->object);
timer->initialized = EINA_FALSE;
timer->in = -1.0;
timer->constructed = EINA_TRUE;
return obj;
}
EOLIAN static Eo *
_efl_loop_timer_efl_object_finalize(Eo *obj, Efl_Loop_Timer_Data *pd)
{
if (pd->at < ecore_loop_time_get())
{
pd->at = ecore_time_get() + pd->in;
}
else
{
pd->at += pd->in;
}
if (pd->at < ecore_loop_time_get()) pd->at = ecore_time_get() + pd->in;
else pd->at += pd->in;
if (pd->in < 0)
pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS);
pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS);
if (pd->in < 0.0)
{
ERR("You need to specify the interval of a timer to create a valid timer.");
return NULL;
}
pd->initialized = EINA_TRUE;
pd->finalized = EINA_TRUE;
_efl_loop_timer_set(pd, pd->at, pd->in);
return efl_finalize(efl_super(obj, MY_CLASS));
}
typedef struct _Ecore_Timer_Legacy Ecore_Timer_Legacy;
struct _Ecore_Timer_Legacy
{
Ecore_Task_Cb func;
const void *data;
Eina_Bool inside_call : 1;
Eina_Bool delete_me : 1;
};
static void
_ecore_timer_legacy_del(void *data, const Efl_Event *event EINA_UNUSED)
{
Ecore_Timer_Legacy *legacy = data;
free(legacy);
free(data);
}
static void
@ -181,11 +156,10 @@ _ecore_timer_legacy_tick(void *data, const Efl_Event *event)
Ecore_Timer_Legacy *legacy = data;
legacy->inside_call = 1;
if (!_ecore_call_task_cb(legacy->func, (void*)legacy->data) ||
if (!_ecore_call_task_cb(legacy->func, (void *)legacy->data) ||
legacy->delete_me)
efl_del(event->object);
else
legacy->inside_call = 0;
else legacy->inside_call = 0;
}
EFL_CALLBACKS_ARRAY_DEFINE(legacy_timer,
@ -193,9 +167,7 @@ EFL_CALLBACKS_ARRAY_DEFINE(legacy_timer,
{ EFL_EVENT_DEL, _ecore_timer_legacy_del });
EAPI Ecore_Timer *
ecore_timer_add(double in,
Ecore_Task_Cb func,
const void *data)
ecore_timer_add(double in, Ecore_Task_Cb func, const void *data)
{
Ecore_Timer_Legacy *legacy;
Eo *timer;
@ -210,14 +182,11 @@ ecore_timer_add(double in,
efl_event_callback_array_add(efl_added, legacy_timer(), legacy),
efl_key_data_set(efl_added, "_legacy", legacy),
efl_loop_timer_interval_set(efl_added, in));
return timer;
}
EAPI Ecore_Timer *
ecore_timer_loop_add(double in,
Ecore_Task_Cb func,
const void *data)
ecore_timer_loop_add(double in, Ecore_Task_Cb func, const void *data)
{
Ecore_Timer_Legacy *legacy;
Eo *timer;
@ -233,7 +202,6 @@ ecore_timer_loop_add(double in,
efl_key_data_set(efl_added, "_legacy", legacy),
efl_loop_timer_loop_reset(efl_added),
efl_loop_timer_interval_set(efl_added, in));
return timer;
}
@ -256,41 +224,28 @@ ecore_timer_del(Ecore_Timer *timer)
return NULL;
}
data = (void*) legacy->data;
if (legacy->inside_call)
legacy->delete_me = EINA_TRUE;
else
efl_del(timer);
data = (void *)legacy->data;
if (legacy->inside_call) legacy->delete_me = EINA_TRUE;
else efl_del(timer);
return data;
}
EOLIAN static void
_efl_loop_timer_interval_set(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer, double in)
{
EINA_MAIN_LOOP_CHECK_RETURN;
if (in < 0.0) in = 0.0;
timer->in = in;
}
EOLIAN static double
_efl_loop_timer_interval_get(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
{
double ret = -1.0;
EINA_MAIN_LOOP_CHECK_RETURN_VAL(ret);
ret = timer->in;
return ret;
return timer->in;
}
EOLIAN static void
_efl_loop_timer_delay(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *pd, double add)
{
EINA_MAIN_LOOP_CHECK_RETURN;
_efl_loop_timer_util_delay(pd, add);
}
@ -298,23 +253,20 @@ EOLIAN static void
_efl_loop_timer_reset(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
{
double now, add;
EINA_MAIN_LOOP_CHECK_RETURN;
if (!timer->loop_data) return;
// Do not reset the current timer while inside the callback
if (timer_current == timer) return ;
if (timer->loop_data->timer_current == timer) return;
now = ecore_time_get();
if (!timer->initialized)
{
timer->at = now;
return;
}
if (timer->frozen)
add = timer->pending;
else
add = timer->at - now;
if (timer->frozen) add = timer->pending;
else add = timer->at - now;
_efl_loop_timer_util_delay(timer, timer->in - add);
}
@ -322,102 +274,80 @@ EOLIAN static void
_efl_loop_timer_loop_reset(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
{
double now, add;
EINA_MAIN_LOOP_CHECK_RETURN;
if (!timer->loop_data) return;
// Do not reset the current timer while inside the callback
if (timer_current == timer) return ;
if (timer->loop_data->timer_current == timer) return;
now = ecore_loop_time_get();
if (!timer->initialized)
{
timer->at = now;
return ;
return;
}
if (timer->frozen)
add = timer->pending;
else
add = timer->at - now;
if (timer->frozen) add = timer->pending;
else add = timer->at - now;
_efl_loop_timer_util_delay(timer, timer->in - add);
}
EOLIAN static double
_efl_loop_timer_pending_get(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
{
double now;
double ret = 0.0;
EINA_MAIN_LOOP_CHECK_RETURN_VAL(ret);
double now, ret = 0.0;
now = ecore_time_get();
if (timer->frozen)
ret = timer->pending;
else
ret = timer->at - now;
if (timer->frozen) ret = timer->pending;
else ret = timer->at - now;
return ret;
}
EAPI void
ecore_timer_freeze(Ecore_Timer *timer)
{
EINA_MAIN_LOOP_CHECK_RETURN;
ECORE_TIMER_CHECK(timer);
efl_event_freeze(timer);
}
EOLIAN static void
_efl_loop_timer_efl_object_event_freeze(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
_efl_loop_timer_efl_object_event_freeze(Eo *obj, Efl_Loop_Timer_Data *timer)
{
double now;
EINA_MAIN_LOOP_CHECK_RETURN;
efl_event_freeze(efl_super(obj, MY_CLASS));
/* Timer already frozen */
if (timer->frozen)
return;
// Timer already frozen
if (timer->frozen) return;
if (EINA_UNLIKELY(!timer->initialized))
{
ERR("Attempt freezing an non initialized timer.");
ERR("Attempt freezing an non unfinalized timer.");
return;
}
now = ecore_loop_time_get();
now = efl_loop_time_get(timer->loop);
timer->pending = timer->at - now;
timer->at = 0.0;
timer->frozen = 1;
_efl_loop_timer_util_instanciate(timer);
_efl_loop_timer_util_instanciate(timer->loop_data, timer);
}
EAPI Eina_Bool
ecore_timer_freeze_get(Ecore_Timer *timer)
{
int r = 0;
EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE);
r = efl_event_freeze_count_get(timer);
return !!r;
return !!efl_event_freeze_count_get(timer);
}
EOLIAN static int
_efl_loop_timer_efl_object_event_freeze_count_get(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
{
EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
return timer->frozen;
}
EAPI void
ecore_timer_thaw(Ecore_Timer *timer)
{
EINA_MAIN_LOOP_CHECK_RETURN;
ECORE_TIMER_CHECK(timer);
efl_event_thaw(timer);
}
@ -427,17 +357,16 @@ _efl_loop_timer_efl_object_event_thaw(Eo *obj, Efl_Loop_Timer_Data *timer)
{
double now;
EINA_MAIN_LOOP_CHECK_RETURN;
efl_event_thaw(efl_super(obj, MY_CLASS));
/* Timer not frozen */
if (!timer->frozen)
return ;
if (!timer->frozen) return; // Timer not frozen
suspended = eina_inlist_remove(suspended, EINA_INLIST_GET(timer));
if (timer->loop_data)
{
timer->loop_data->suspended = eina_inlist_remove
(timer->loop_data->suspended, EINA_INLIST_GET(timer));
}
now = ecore_time_get();
_efl_loop_timer_set(timer, timer->pending + now, timer->in);
}
@ -448,139 +377,130 @@ ecore_timer_dump(void)
}
static void
_efl_loop_timer_util_instanciate(Efl_Loop_Timer_Data *timer)
_efl_loop_timer_util_loop_clear(Efl_Loop_Timer_Data *pd)
{
Efl_Loop_Timer_Data *t2;
Eina_Inlist *first;
if (!pd->loop_data) return;
// Check if we are the current timer, if so move along
if (pd->loop_data->timer_current == pd)
pd->loop_data->timer_current = (Efl_Loop_Timer_Data *)
EINA_INLIST_GET(pd)->next;
// Remove the timer from all possible pending list
first = eina_inlist_first(EINA_INLIST_GET(timer));
if (first == timers)
timers = eina_inlist_remove(timers, EINA_INLIST_GET(timer));
else if (first == suspended)
suspended = eina_inlist_remove(suspended, EINA_INLIST_GET(timer));
first = eina_inlist_first(EINA_INLIST_GET(pd));
if (first == pd->loop_data->timers)
pd->loop_data->timers = eina_inlist_remove
(pd->loop_data->timers, EINA_INLIST_GET(pd));
else if (first == pd->loop_data->suspended)
pd->loop_data->suspended = eina_inlist_remove
(pd->loop_data->suspended, EINA_INLIST_GET(pd));
}
static void
_efl_loop_timer_util_instanciate(Efl_Loop_Data *loop, Efl_Loop_Timer_Data *timer)
{
Efl_Loop_Timer_Data *t2;
if (!loop) return;
_efl_loop_timer_util_loop_clear(timer);
// And start putting it back where it belong
if (!timer->listening || timer->frozen || timer->at <= 0.0 || timer->in < 0.0)
if ((!timer->listening) || (timer->frozen) ||
(timer->at <= 0.0) || (timer->in < 0.0))
{
suspended = eina_inlist_prepend(suspended, EINA_INLIST_GET(timer));
return ;
loop->suspended = eina_inlist_prepend(loop->suspended,
EINA_INLIST_GET(timer));
return;
}
if (!timer->initialized)
{
ERR("Trying to instantiate an uninitialized timer is impossible.");
return ;
return;
}
EINA_INLIST_REVERSE_FOREACH(timers, t2)
EINA_INLIST_REVERSE_FOREACH(loop->timers, t2)
{
if (timer->at > t2->at)
{
timers = eina_inlist_append_relative(timers,
EINA_INLIST_GET(timer),
EINA_INLIST_GET(t2));
loop->timers = eina_inlist_append_relative(loop->timers,
EINA_INLIST_GET(timer),
EINA_INLIST_GET(t2));
return;
}
}
timers = eina_inlist_prepend(timers, EINA_INLIST_GET(timer));
loop->timers = eina_inlist_prepend(loop->timers, EINA_INLIST_GET(timer));
}
static void
_efl_loop_timer_util_delay(Efl_Loop_Timer_Data *timer,
double add)
_efl_loop_timer_util_delay(Efl_Loop_Timer_Data *timer, double add)
{
if (!timer->initialized)
{
ERR("Impossible to delay an uninitialized timer.");
return ;
return;
}
if (timer->frozen)
{
timer->pending += add;
return ;
return;
}
_efl_loop_timer_set(timer, timer->at + add, timer->in);
}
EOLIAN static void
_efl_loop_timer_efl_object_parent_set(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *pd, Efl_Object *parent)
_efl_loop_timer_efl_object_parent_set(Eo *obj, Efl_Loop_Timer_Data *pd, Efl_Object *parent)
{
Eina_Inlist *first;
first = eina_inlist_first(EINA_INLIST_GET(pd));
if (first == timers)
timers = eina_inlist_remove(timers, EINA_INLIST_GET(pd));
else if (first == suspended)
suspended = eina_inlist_remove(suspended, EINA_INLIST_GET(pd));
efl_parent_set(efl_super(obj, EFL_LOOP_TIMER_CLASS), parent);
if (efl_parent_get(obj) != parent)
return ;
if ((!pd->constructed) || (!pd->finalized)) return;
if (parent != NULL)
{
_efl_loop_timer_util_instanciate(pd);
pd->noparent = EINA_FALSE;
}
else
{
pd->noparent = EINA_TRUE;
}
_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 (efl_parent_get(obj) != parent) return;
_efl_loop_timer_util_instanciate(pd->loop_data, pd);
if (parent != NULL) pd->noparent = EINA_FALSE;
else pd->noparent = EINA_TRUE;
}
EOLIAN static void
_efl_loop_timer_efl_object_destructor(Eo *obj, Efl_Loop_Timer_Data *pd)
{
Eina_Inlist *first;
// Check if we are the current timer, if so move along
if (timer_current == pd)
timer_current = (Efl_Loop_Timer_Data *)EINA_INLIST_GET(pd)->next;
// Remove the timer from all possible pending list
first = eina_inlist_first(EINA_INLIST_GET(pd));
if (first == timers)
timers = eina_inlist_remove(timers, EINA_INLIST_GET(pd));
else if (first == suspended)
suspended = eina_inlist_remove(suspended, EINA_INLIST_GET(pd));
_efl_loop_timer_util_loop_clear(pd);
efl_destructor(efl_super(obj, MY_CLASS));
}
void
_efl_loop_timer_shutdown(void)
{
timer_current = NULL;
}
void
_efl_loop_timer_enable_new(void)
_efl_loop_timer_enable_new(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
{
Efl_Loop_Timer_Data *timer;
if (!timers_added) return;
timers_added = 0;
EINA_INLIST_FOREACH(timers, timer) timer->just_added = 0;
if (!pd->timers_added) return;
pd->timers_added = 0;
EINA_INLIST_FOREACH(pd->timers, timer) timer->just_added = 0;
}
int
_efl_loop_timers_exists(void)
_efl_loop_timers_exists(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
{
return !!timers;
return !!pd->timers;
}
static inline Ecore_Timer *
_efl_loop_timer_first_get(void)
_efl_loop_timer_first_get(Eo *ob EINA_UNUSED, Efl_Loop_Data *pd)
{
Efl_Loop_Timer_Data *timer;
EINA_INLIST_FOREACH(timers, timer)
if (!timer->just_added) return timer->object;
EINA_INLIST_FOREACH(pd->timers, timer)
{
if (!timer->just_added) return timer->object;
}
return NULL;
}
@ -595,41 +515,40 @@ _efl_loop_timer_after_get(Efl_Loop_Timer_Data *base)
{
if (EINA_UNLIKELY(!timer->initialized)) continue; // This shouldn't happen
if (timer->at >= maxtime) break;
if (!timer->just_added)
valid_timer = timer;
if (!timer->just_added) valid_timer = timer;
}
return valid_timer;
}
double
_efl_loop_timer_next_get(void)
_efl_loop_timer_next_get(Eo *obj, Efl_Loop_Data *pd)
{
Ecore_Timer *object;
Efl_Loop_Timer_Data *first;
double now;
double in;
object = _efl_loop_timer_first_get();
object = _efl_loop_timer_first_get(obj, pd);
if (!object) return -1;
first = _efl_loop_timer_after_get(efl_data_scope_get(object, MY_CLASS));
now = ecore_loop_time_get();
in = first->at - now;
if (in < 0) in = 0;
return in;
}
static inline void
_efl_loop_timer_reschedule(Efl_Loop_Timer_Data *timer,
double when)
_efl_loop_timer_reschedule(Efl_Loop_Timer_Data *timer, double when)
{
if (timer->frozen) return;
if (timers && !timer->noparent)
timers = eina_inlist_remove(timers, EINA_INLIST_GET(timer));
if (timer->loop_data)
{
if (timer->loop_data->timers && (!timer->noparent))
timer->loop_data->timers = eina_inlist_remove
(timer->loop_data->timers, EINA_INLIST_GET(timer));
}
/* if the timer would have gone off more than 15 seconds ago,
* assume that the system hung and set the timer to go off
@ -647,51 +566,51 @@ _efl_loop_timer_reschedule(Efl_Loop_Timer_Data *timer,
}
void
_efl_loop_timer_expired_timers_call(double when)
_efl_loop_timer_expired_timers_call(Eo *obj, Efl_Loop_Data *pd, double when)
{
/* call the first expired timer until no expired timers exist */
while (_efl_loop_timer_expired_call(when)) ;
// call the first expired timer until no expired timers exist
while (_efl_loop_timer_expired_call(obj, pd, when));
}
int
_efl_loop_timer_expired_call(double when)
_efl_loop_timer_expired_call(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, double when)
{
if (!timers) return 0;
if (last_check > when)
if (!pd->timers) return 0;
if (pd->last_check > when)
{
Efl_Loop_Timer_Data *timer;
/* User set time backwards */
EINA_INLIST_FOREACH(timers, timer) timer->at -= (last_check - when);
// User set time backwards
EINA_INLIST_FOREACH(pd->timers, timer)
timer->at -= (pd->last_check - when);
}
last_check = when;
pd->last_check = when;
if (!timer_current)
{
/* regular main loop, start from head */
timer_current = (Efl_Loop_Timer_Data *)timers;
}
if (!pd->timer_current) // regular main loop, start from head
pd->timer_current = (Efl_Loop_Timer_Data *)pd->timers;
else
{
/* recursive main loop, continue from where we were */
Efl_Loop_Timer_Data *timer_old = timer_current;
// recursive main loop, continue from where we were
Efl_Loop_Timer_Data *timer_old = pd->timer_current;
timer_current = (Efl_Loop_Timer_Data *)EINA_INLIST_GET(timer_current)->next;
pd->timer_current = (Efl_Loop_Timer_Data *)
EINA_INLIST_GET(pd->timer_current)->next;
_efl_loop_timer_reschedule(timer_old, when);
}
while (timer_current)
while (pd->timer_current)
{
Efl_Loop_Timer_Data *timer = timer_current;
Efl_Loop_Timer_Data *timer = pd->timer_current;
if (timer->at > when)
{
timer_current = NULL; /* ended walk, next should restart. */
pd->timer_current = NULL; // ended walk, next should restart.
return 0;
}
if (timer->just_added)
{
timer_current = (Efl_Loop_Timer_Data *)EINA_INLIST_GET(timer_current)->next;
pd->timer_current = (Efl_Loop_Timer_Data *)
EINA_INLIST_GET(pd->timer_current)->next;
continue;
}
@ -700,11 +619,11 @@ _efl_loop_timer_expired_call(double when)
efl_event_callback_call(timer->object, EFL_LOOP_TIMER_EVENT_TICK, NULL);
eina_evlog("-timer", timer, 0.0, NULL);
/* may have changed in recursive main loops */
/* this current timer can not die yet as we hold a reference on it */
if (timer_current)
timer_current = (Efl_Loop_Timer_Data *)EINA_INLIST_GET(timer_current)->next;
// may have changed in recursive main loops
// this current timer can not die yet as we hold a reference on it
if (pd->timer_current)
pd->timer_current = (Efl_Loop_Timer_Data *)
EINA_INLIST_GET(pd->timer_current)->next;
_efl_loop_timer_reschedule(timer, when);
efl_unref(timer->object);
}
@ -712,19 +631,17 @@ _efl_loop_timer_expired_call(double when)
}
static void
_efl_loop_timer_set(Efl_Loop_Timer_Data *timer,
double at,
double in)
_efl_loop_timer_set(Efl_Loop_Timer_Data *timer, double at, double in)
{
timers_added = 1;
if (!timer->loop_data) return;
timer->loop_data->timers_added = 1;
timer->at = at;
timer->in = in;
timer->just_added = 1;
timer->initialized = 1;
timer->frozen = 0;
timer->pending = 0.0;
_efl_loop_timer_util_instanciate(timer);
_efl_loop_timer_util_instanciate(timer->loop_data, timer);
}
#include "efl_loop_timer.eo.c"

717
src/lib/ecore/efl_loop.c Normal file
View File

@ -0,0 +1,717 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include "Ecore.h"
#include "ecore_private.h"
#include "ecore_main_common.h"
typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data;
typedef struct _Efl_Internal_Promise Efl_Internal_Promise;
struct _Efl_Loop_Promise_Simple_Data
{
union {
Ecore_Timer *timer;
Ecore_Idler *idler;
};
Eina_Promise *promise;
};
GENERIC_ALLOC_SIZE_DECLARE(Efl_Loop_Promise_Simple_Data);
EOLIAN static Efl_Loop_Message_Handler *
_efl_loop_message_handler_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Loop *loop, const Efl_Class *klass)
{
Message_Handler mh = { 0 }, *mh2;
Efl_Loop_Data *ld = efl_data_scope_get(loop, EFL_LOOP_CLASS);
unsigned int i, n;
if (!ld) return NULL;
n = eina_inarray_count(ld->message_handlers);
for (i = 0; i < n; i++)
{
mh2 = eina_inarray_nth(ld->message_handlers, i);
if (mh2->klass == klass) return mh2->handler;
}
mh.klass = klass;
mh.handler = efl_add(klass, loop);
eina_inarray_push(ld->message_handlers, &mh);
return mh.handler;
}
Efl_Version _app_efl_version = { 0, 0, 0, 0, NULL, NULL };
Eo *_mainloop_singleton = NULL;
Efl_Loop_Data *_mainloop_singleton_data = NULL;
static void
_mainloop_singleton_cb_del(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED)
{
_mainloop_singleton = NULL;
_mainloop_singleton_data = NULL;
}
EFL_CALLBACKS_ARRAY_DEFINE(_mainloop_singleton_callbacks,
{ EFL_EVENT_DEL, _mainloop_singleton_cb_del });
EOLIAN static Efl_Loop *
_efl_loop_main_get(Efl_Class *klass EINA_UNUSED, void *_pd EINA_UNUSED)
{
if (_mainloop_singleton) return _mainloop_singleton;
_mainloop_singleton = efl_add(EFL_LOOP_CLASS, NULL);
_mainloop_singleton_data = efl_data_scope_get(_mainloop_singleton,
EFL_LOOP_CLASS);
efl_event_callback_array_add(_mainloop_singleton,
_mainloop_singleton_callbacks(), NULL);
return _mainloop_singleton;
}
EAPI Eo *
ecore_main_loop_get(void)
{
return efl_loop_main_get(EFL_LOOP_CLASS);
}
EOLIAN static void
_efl_loop_iterate(Eo *obj, Efl_Loop_Data *pd)
{
_ecore_main_loop_iterate(obj, pd);
}
EOLIAN static int
_efl_loop_iterate_may_block(Eo *obj, Efl_Loop_Data *pd, int may_block)
{
return _ecore_main_loop_iterate_may_block(obj, pd, may_block);
}
// FIXME: This should return an Eina_Value, but that doesn't work at the moment
EOLIAN static Eina_Value *
_efl_loop_begin(Eo *obj, Efl_Loop_Data *pd)
{
_ecore_main_loop_begin(obj, pd);
return &(pd->exit_code);
}
EOLIAN static void
_efl_loop_quit(Eo *obj, Efl_Loop_Data *pd, Eina_Value exit_code)
{
_ecore_main_loop_quit(obj, pd);
pd->exit_code = exit_code;
}
EOLIAN static void
_efl_loop_time_set(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, double t)
{
pd->loop_time = t;
}
EOLIAN static double
_efl_loop_time_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
{
return pd->loop_time;
}
EAPI void
efl_exit(int exit_code)
{
Eina_Value v = EINA_VALUE_EMPTY;
eina_value_setup(&v, EINA_VALUE_TYPE_INT);
eina_value_set(&v, &exit_code);
efl_loop_quit(ecore_main_loop_get(), v);
}
EOLIAN static Efl_Object *
_efl_loop_efl_object_provider_find(Eo *obj, Efl_Loop_Data *pd, const Efl_Object *klass)
{
Efl_Object *r;
if (klass == EFL_LOOP_CLASS) return obj;
r = eina_hash_find(pd->providers, &klass);
if (r) return r;
return efl_provider_find(efl_super(obj, EFL_LOOP_CLASS), klass);
}
EAPI int
efl_loop_exit_code_process(Eina_Value *value)
{
const Eina_Value_Type *t = eina_value_type_get(value);
int r = 0;
if (t == EINA_VALUE_TYPE_UCHAR ||
t == EINA_VALUE_TYPE_USHORT ||
t == EINA_VALUE_TYPE_UINT ||
t == EINA_VALUE_TYPE_ULONG ||
t == EINA_VALUE_TYPE_UINT64 ||
t == EINA_VALUE_TYPE_CHAR ||
t == EINA_VALUE_TYPE_SHORT ||
t == EINA_VALUE_TYPE_INT ||
t == EINA_VALUE_TYPE_LONG ||
t == EINA_VALUE_TYPE_INT64 ||
t == EINA_VALUE_TYPE_FLOAT ||
t == EINA_VALUE_TYPE_DOUBLE)
{
Eina_Value v = EINA_VALUE_EMPTY;
eina_value_setup(&v, EINA_VALUE_TYPE_INT);
if (!eina_value_convert(&v, value)) r = -1;
else eina_value_get(&v, &v);
}
else
{
FILE *out = stdout;
char *msg;
msg = eina_value_to_string(value);
if (t == EINA_VALUE_TYPE_ERROR)
{
r = -1;
out = stderr;
}
fprintf(out, "%s\n", msg);
}
return r;
}
static void
_poll_trigger(void *data, const Efl_Event *event)
{
Eo *parent = efl_parent_get(event->object);
efl_event_callback_call(parent, data, NULL);
}
static void
_check_event_catcher_add(void *data, const Efl_Event *event)
{
const Efl_Callback_Array_Item *array = event->info;
Efl_Loop_Data *pd = data;
int i;
for (i = 0; array[i].desc != NULL; i++)
{
if (array[i].desc == EFL_LOOP_EVENT_IDLE)
{
++pd->idlers;
}
// XXX: all the below are kind of bad. ecore_pollers were special.
// they all woke up at the SAME time based on interval, (all pollers
// of interval 1 woke up together, those with 2 woke up when 1 and
// 2 woke up, 4 woke up together along with 1 and 2 etc.
// the below means they will just go off whenever but at a pre
// defined interval - 1/60th, 6 and 66 seconds. not really great
// pollers probably should be less frequent that 1/60th even on poll
// high, medium probably down to 1-2 sec and low - yes maybe 30 or 60
// sec... still - not timed to wake up together. :(
else if (array[i].desc == EFL_LOOP_EVENT_POLL_HIGH)
{
if (!pd->poll_high)
{
// Would be better to have it in sync with normal wake up
// of the main loop for better energy efficiency, I guess.
pd->poll_high = efl_add
(EFL_LOOP_TIMER_CLASS, event->object,
efl_event_callback_add(efl_added,
EFL_LOOP_TIMER_EVENT_TICK,
_poll_trigger,
EFL_LOOP_EVENT_POLL_HIGH),
efl_loop_timer_interval_set(efl_added, 1.0 / 60.0));
}
++pd->pollers.high;
}
else if (array[i].desc == EFL_LOOP_EVENT_POLL_MEDIUM)
{
if (!pd->poll_medium)
{
pd->poll_medium = efl_add
(EFL_LOOP_TIMER_CLASS, event->object,
efl_event_callback_add(efl_added,
EFL_LOOP_TIMER_EVENT_TICK,
_poll_trigger,
EFL_LOOP_EVENT_POLL_MEDIUM),
efl_loop_timer_interval_set(efl_added, 6));
}
++pd->pollers.medium;
}
else if (array[i].desc == EFL_LOOP_EVENT_POLL_LOW)
{
if (!pd->poll_low)
{
pd->poll_low = efl_add
(EFL_LOOP_TIMER_CLASS, event->object,
efl_event_callback_add(efl_added,
EFL_LOOP_TIMER_EVENT_TICK,
_poll_trigger,
EFL_LOOP_EVENT_POLL_LOW),
efl_loop_timer_interval_set(efl_added, 66));
}
++pd->pollers.low;
}
}
}
static void
_check_event_catcher_del(void *data, const Efl_Event *event)
{
const Efl_Callback_Array_Item *array = event->info;
Efl_Loop_Data *pd = data;
int i;
for (i = 0; array[i].desc != NULL; i++)
{
if (array[i].desc == EFL_LOOP_EVENT_IDLE)
{
--pd->idlers;
}
else if (array[i].desc == EFL_LOOP_EVENT_POLL_HIGH)
{
--pd->pollers.high;
if (!pd->pollers.high)
{
ecore_timer_del(pd->poll_high);
pd->poll_high = NULL;
}
}
else if (array[i].desc == EFL_LOOP_EVENT_POLL_MEDIUM)
{
--pd->pollers.medium;
if (!pd->pollers.medium)
{
ecore_timer_del(pd->poll_medium);
pd->poll_medium = NULL;
}
}
else if (array[i].desc == EFL_LOOP_EVENT_POLL_LOW)
{
--pd->pollers.low;
if (!pd->pollers.low)
{
ecore_timer_del(pd->poll_low);
pd->poll_low = NULL;
}
}
}
}
EFL_CALLBACKS_ARRAY_DEFINE(event_catcher_watch,
{ EFL_EVENT_CALLBACK_ADD, _check_event_catcher_add },
{ EFL_EVENT_CALLBACK_DEL, _check_event_catcher_del });
EOLIAN static Efl_Object *
_efl_loop_efl_object_constructor(Eo *obj, Efl_Loop_Data *pd)
{
obj = efl_constructor(efl_super(obj, EFL_LOOP_CLASS));
if (!obj) return NULL;
efl_event_callback_array_add(obj, event_catcher_watch(), pd);
pd->loop_time = ecore_time_get();
pd->providers = eina_hash_pointer_new(EINA_FREE_CB(efl_unref));
pd->message_handlers = eina_inarray_new(sizeof(Message_Handler), 32);
#ifdef HAVE_EPOLL
pd->epoll_fd = -1;
#endif
#ifdef USE_G_MAIN_LOOP
pd->timer_fd = -1;
#endif
return obj;
}
EOLIAN static void
_efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd)
{
_ecore_main_content_clear(pd);
eina_hash_free(pd->providers);
pd->providers = NULL;
efl_del(pd->poll_low);
pd->poll_low = NULL;
efl_del(pd->poll_medium);
pd->poll_medium = NULL;
efl_del(pd->poll_high);
pd->poll_high = NULL;
eina_inarray_free(pd->message_handlers);
pd->message_handlers = NULL;
efl_destructor(efl_super(obj, EFL_LOOP_CLASS));
}
static void
_efl_loop_arguments_cleanup(Eina_Array *arga)
{
Eina_Stringshare *s;
while ((s = eina_array_pop(arga))) eina_stringshare_del(s);
eina_array_free(arga);
}
static void
_efl_loop_arguments_send(void *data, const Efl_Event *ev EINA_UNUSED)
{
static Eina_Bool initialization = EINA_TRUE;
Efl_Loop_Arguments arge;
Eina_Array *arga = data;
arge.argv = arga;
arge.initialization = initialization;
initialization = EINA_FALSE;
efl_event_callback_call(ecore_main_loop_get(),
EFL_LOOP_EVENT_ARGUMENTS, &arge);
_efl_loop_arguments_cleanup(arga);
}
static void
_efl_loop_arguments_cancel(void *data, const Efl_Event *ev EINA_UNUSED)
{
_efl_loop_arguments_cleanup(data);
}
// It doesn't make sense to send those argument to any other mainloop
// As it also doesn't make sense to allow anyone to override this, so
// should be internal for sure, not even protected.
EAPI void
ecore_loop_arguments_send(int argc, const char **argv)
{
Eina_Future *job;
Eina_Array *arga;
int i = 0;
arga = eina_array_new(argc);
for (i = 0; i < argc; i++)
eina_array_push(arga, eina_stringshare_add(argv[i]));
job = eina_future_then(efl_loop_job(ecore_main_loop_get()),
_efl_loop_arguments_send, arga);
efl_future_Eina_FutureXXX_then(ecore_main_loop_get(), job);
}
// Only one main loop handle for now
void
ecore_loop_future_register(Efl_Loop *l, Efl_Future *f)
{
Efl_Loop_Data *pd;
if (l == ML_OBJ) pd = ML_DAT;
else pd = efl_data_scope_get(l, EFL_LOOP_CLASS);
if (!pd) return;
pd->pending_futures = eina_list_append(pd->pending_futures, f);
}
void
ecore_loop_future_unregister(Efl_Loop *l, Efl_Future *f)
{
Efl_Loop_Data *pd;
if (l == ML_OBJ) pd = ML_DAT;
else pd = efl_data_scope_get(l, EFL_LOOP_CLASS);
if (!pd) return;
pd->pending_futures = eina_list_remove(pd->pending_futures, f);
}
void
ecore_loop_promise_register(Efl_Loop *l, Efl_Promise *p)
{
Efl_Loop_Data *pd;
if (l == ML_OBJ) pd = ML_DAT;
else pd = efl_data_scope_get(l, EFL_LOOP_CLASS);
if (!pd) return;
pd->pending_promises = eina_list_append(pd->pending_promises, p);
}
void
ecore_loop_promise_unregister(Efl_Loop *l, Efl_Promise *p)
{
Efl_Loop_Data *pd;
if (l == ML_OBJ) pd = ML_DAT;
else pd = efl_data_scope_get(l, EFL_LOOP_CLASS);
if (!pd) return;
pd->pending_promises = eina_list_remove(pd->pending_promises, p);
}
static Eina_Future *
_efl_loop_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));
}
EOLIAN static void
_efl_loop_throttle_set(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, double amount)
{
pd->throttle = ((double)amount) * 1000000.0;
}
EOLIAN static double
_efl_loop_throttle_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
{
return (double)(pd->throttle) / 1000000.0;
}
static void
_efl_loop_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_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_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_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);
// 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_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_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_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_timeout_done, 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);
// 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;
}
static Eina_Bool
_efl_loop_register(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, const Efl_Class *klass, const Efl_Object *provider)
{
// The passed object does not provide that said class.
if (!efl_isa(provider, klass)) return EINA_FALSE;
// Note: I would prefer to use efl_xref here, but I can't figure a nice way to
// call efl_xunref on hash destruction.
return eina_hash_add(pd->providers, &klass, efl_ref(provider));
}
static Eina_Bool
_efl_loop_unregister(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, const Efl_Class *klass, const Efl_Object *provider)
{
return eina_hash_del(pd->providers, &klass, provider);
}
void
_efl_loop_messages_filter(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, void *handler_pd)
{
Message *msg;
pd->message_walking++;
EINA_INLIST_FOREACH(pd->message_queue, msg)
{
if ((msg->handler) && (msg->message) && (!msg->delete_me))
{
if (!_ecore_event_do_filter(handler_pd,
msg->handler, msg->message))
{
efl_del(msg->message);
msg->handler = NULL;
msg->message = NULL;
msg->delete_me = EINA_TRUE;
}
}
}
pd->message_walking--;
}
void
_efl_loop_messages_call(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, void *func, void *data)
{
Message *msg;
pd->message_walking++;
EINA_INLIST_FOREACH(pd->message_queue, msg)
{
if ((msg->handler) && (msg->message) && (!msg->delete_me))
{
Eina_Bool (*fn) (void *data, void *handler, void *msg);
fn = func;
if (!fn(data, msg->handler, msg->message))
{
efl_del(msg->message);
msg->handler = NULL;
msg->message = NULL;
msg->delete_me = EINA_TRUE;
}
}
}
pd->message_walking--;
}
EOLIAN static Eina_Bool
_efl_loop_message_process(Eo *obj, Efl_Loop_Data *pd)
{
if (!pd->message_queue) return EINA_FALSE;
pd->message_walking++;
_ecore_event_filters_call(obj, pd);
while (pd->message_queue)
{
Message *msg = (Message *)pd->message_queue;
if (!msg->delete_me)
efl_loop_message_handler_message_call(msg->handler, msg->message);
else
{
if (msg->message) efl_del(msg->message);
pd->message_queue =
eina_inlist_remove(pd->message_queue,
pd->message_queue);
free(msg);
}
}
pd->message_walking--;
if (pd->message_walking == 0)
{
Message *msg;
EINA_INLIST_FREE(pd->message_queue, msg)
{
if (msg->message)
{
if (!msg->delete_me)
ERR("Found unprocessed event msg=%p handler=%p on queue",
msg->message, msg->handler);
efl_del(msg->message);
}
else free(msg);
}
}
return EINA_TRUE;
}
EOLIAN static Eina_Bool
_efl_loop_message_exists(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
{
if (pd->message_queue) return EINA_TRUE;
return EINA_FALSE;
}
EWAPI void
efl_build_version_set(int vmaj, int vmin, int vmic, int revision,
const char *flavor, const char *build_id)
{
// note: EFL has not been initialized yet at this point (ie. no eina call)
_app_efl_version.major = vmaj;
_app_efl_version.minor = vmin;
_app_efl_version.micro = vmic;
_app_efl_version.revision = revision;
free((char *)_app_efl_version.flavor);
free((char *)_app_efl_version.build_id);
_app_efl_version.flavor = flavor ? strdup(flavor) : NULL;
_app_efl_version.build_id = build_id ? strdup(build_id) : NULL;
}
EOLIAN static const Efl_Version *
_efl_loop_app_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
{
return &_app_efl_version;
}
EOLIAN static const Efl_Version *
_efl_loop_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
{
/* vanilla EFL: flavor = NULL */
static const Efl_Version version = {
.major = VMAJ,
.minor = VMIN,
.micro = VMIC,
.revision = VREV,
.build_id = EFL_BUILD_ID,
.flavor = NULL
};
return &version;
}
EAPI Eina_Future_Scheduler *
efl_loop_future_scheduler_get(Eo *obj)
{
if (!obj) return NULL;
if (efl_isa(obj, EFL_LOOP_CLASS))
return _ecore_event_future_scheduler_get();
return efl_loop_future_scheduler_get(efl_loop_get(obj));
}
#include "efl_loop.eo.c"

View File

@ -77,7 +77,24 @@ class Efl.Loop (Efl.Object)
This has higher priority, for low priority use
@.idle
]]
return: ptr(Eina.Future) @owned /* TODO: future<void> */; [[The future handle.]]
return: ptr(Eina.Future) @owned /* TODO: future<void> */; [[The future handle.]]
}
@property throttle {
[[Slow down the loop execution by forcing a sleep for a small
period of time every time the loop iterates/loops.]]
set {}
get {}
values {
amount : double; [[Time to sleep for each "loop iteration"]]
}
}
@property time {
[[The time point when the loop was logically woken up.]]
set {}
get {}
values {
timepoint: double; [[Time in seconds since process specfic start point]]
}
}
idle {
[[A future promise that will be resolved from a clean main
@ -85,7 +102,7 @@ class Efl.Loop (Efl.Object)
This is a low priority version of @.job
]]
return: ptr(Eina.Future) @owned /* TODO: future<void> */; [[The future handle.]]
return: ptr(Eina.Future) @owned /* TODO: future<void> */; [[The future handle.]]
}
timeout {
[[A future promise that will be resolved from a clean main
@ -111,6 +128,22 @@ class Efl.Loop (Efl.Object)
}
return: bool; [[$true if successfully unregistered, $false otherwise.]]
}
message_handler_get @class {
[[ ]]
params {
@in loop: Efl.Loop; [[ ]]
@in klass: const(Efl.Class); [[ ]]
}
return: Efl.Loop.Message.Handler; [[ ]]
}
message_process {
[[ ]]
return: bool; [[ ]]
}
message_exists {
[[ ]]
return: bool; [[ ]]
}
}
events {
idle,enter @restart; [[Event occurs once the main loop enters the idle state.]]

View File

@ -0,0 +1,341 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Ecore.h>
#include "ecore_private.h"
#define MY_CLASS EFL_LOOP_HANDLER_CLASS
//////////////////////////////////////////////////////////////////////////
typedef struct _Efl_Loop_Handler_Data Efl_Loop_Handler_Data;
struct _Efl_Loop_Handler_Data
{
Eo *loop;
Efl_Loop_Data *loop_data;
Ecore_Fd_Handler *handler_fd;
Ecore_Win32_Handler *handler_win32;
void *win32;
int fd;
struct {
unsigned short read;
unsigned short write;
unsigned short error;
unsigned short buffer;
unsigned short prepare;
} references;
Efl_Loop_Handler_Flags flags : 8;
Eina_Bool file : 1;
Eina_Bool constructed : 1;
Eina_Bool finalized : 1;
};
//////////////////////////////////////////////////////////////////////////
static Eina_Bool _cb_handler_fd(void *data, Ecore_Fd_Handler *fd_handler);
static Eina_Bool _cb_handler_buffer(void *data, Ecore_Fd_Handler *fd_handler);
static Eina_Bool _cb_handler_win32(void *data, Ecore_Win32_Handler *win32_handler);
static void _cb_handler_prepare(void *data, Ecore_Fd_Handler *fd_handler);
//////////////////////////////////////////////////////////////////////////
static void
_handler_clear(Efl_Loop_Handler_Data *pd)
{
Eo *obj = pd->loop;
Efl_Loop_Data *loop = pd->loop_data;
if (pd->handler_fd)
_ecore_main_fd_handler_del(obj, loop, pd->handler_fd);
else if (pd->handler_win32)
_ecore_main_win32_handler_del(obj, loop, pd->handler_win32);
pd->handler_fd = NULL;
pd->handler_win32 = NULL;
}
static Ecore_Fd_Handler_Flags
_handler_flags_get(Efl_Loop_Handler_Data *pd)
{
return ((pd->references.read > 0) ? ECORE_FD_READ : 0) |
((pd->references.write > 0) ? ECORE_FD_WRITE : 0) |
((pd->references.error > 0) ? ECORE_FD_ERROR : 0);
}
static void
_handler_active_update(Eo *obj, Efl_Loop_Handler_Data *pd)
{
Ecore_Fd_Handler_Flags flags = _handler_flags_get(pd);
ecore_main_fd_handler_active_set(pd->handler_fd, flags);
if (pd->references.prepare)
ecore_main_fd_handler_prepare_callback_set
(pd->handler_fd, _cb_handler_prepare, obj);
else
ecore_main_fd_handler_prepare_callback_set
(pd->handler_fd, NULL, NULL);
}
static void
_handler_reset(Eo *obj, Efl_Loop_Handler_Data *pd)
{
if ((pd->fd < 0) && (!pd->win32))
{
_handler_clear(pd);
return;
}
if ((!pd->constructed) || (!pd->finalized)) return;
if (pd->fd >= 0)
{
Ecore_Fd_Cb buffer_func = NULL;
void *buffer_data = NULL;
if (pd->references.buffer > 0)
{
buffer_func = _cb_handler_buffer;
buffer_data = obj;
}
if (pd->handler_fd)
_handler_active_update(obj, pd);
else
{
Ecore_Fd_Handler_Flags flags = _handler_flags_get(pd);
if (pd->file)
pd->handler_fd = _ecore_main_fd_handler_add
(pd->loop, pd->loop_data, obj, pd->fd, flags,
_cb_handler_fd, obj, buffer_func, buffer_data,
EINA_TRUE);
else
pd->handler_fd = _ecore_main_fd_handler_add
(pd->loop, pd->loop_data, obj, pd->fd, flags,
_cb_handler_fd, obj, buffer_func, buffer_data,
EINA_FALSE);
if (pd->handler_fd) _handler_active_update(obj, pd);
}
}
else if (pd->win32)
{
pd->handler_win32 = _ecore_main_win32_handler_add
(pd->loop, pd->loop_data, obj, pd->win32, _cb_handler_win32, obj);
}
}
static Eina_Bool
_event_references_update(Efl_Loop_Handler_Data *pd, const Efl_Event *event, int increment)
{
const Efl_Callback_Array_Item *array = event->info;
int i;
Eina_Bool need_reset = EINA_FALSE;
for (i = 0; array[i].desc != NULL; i++)
{
#define REFERENCES_MAP(_desc, _refs) \
if (array[i].desc == _desc) { \
pd->references._refs += increment; \
need_reset = EINA_TRUE; \
continue; \
}
REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_READ, read);
REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_WRITE, write);
REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_ERROR, error);
REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_BUFFER, buffer);
REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_PREPARE, prepare);
}
return need_reset;
}
//////////////////////////////////////////////////////////////////////////
static Eina_Bool
_cb_handler_fd(void *data, Ecore_Fd_Handler *fd_handler EINA_UNUSED)
{
Eo *obj = data;
if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_READ, NULL);
if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_WRITE, NULL);
if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_ERROR, NULL);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_cb_handler_buffer(void *data, Ecore_Fd_Handler *fd_handler EINA_UNUSED)
{
Eo *obj = data;
efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_BUFFER, NULL);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_cb_handler_win32(void *data, Ecore_Win32_Handler *win32_handler EINA_UNUSED)
{
Eo *obj = data;
efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_READ, NULL);
return ECORE_CALLBACK_RENEW;
}
static void
_cb_handler_prepare(void *data, Ecore_Fd_Handler *fd_handler EINA_UNUSED)
{
Eo *obj = data;
efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_PREPARE, NULL);
}
static void
_cb_event_callback_add(void *data, const Efl_Event *event)
{
Efl_Loop_Handler_Data *pd = data;
if (_event_references_update(pd, event, 1))
_handler_reset(event->object, pd);
}
static void
_cb_event_callback_del(void *data, const Efl_Event *event)
{
Efl_Loop_Handler_Data *pd = data;
if (_event_references_update(pd, event, -1))
_handler_reset(event->object, pd);
}
//////////////////////////////////////////////////////////////////////////
EFL_CALLBACKS_ARRAY_DEFINE(_event_callback_watch,
{ EFL_EVENT_CALLBACK_ADD, _cb_event_callback_add },
{ EFL_EVENT_CALLBACK_DEL, _cb_event_callback_del });
static void
_efl_loop_handler_active_set(Eo *obj, Efl_Loop_Handler_Data *pd, Efl_Loop_Handler_Flags flags)
{
pd->flags = flags;
_handler_reset(obj, pd);
}
static Efl_Loop_Handler_Flags
_efl_loop_handler_active_get(Eo *obj EINA_UNUSED, Efl_Loop_Handler_Data *pd)
{
return pd->flags;
}
static void
_efl_loop_handler_fd_set(Eo *obj, Efl_Loop_Handler_Data *pd, int fd)
{
pd->fd = fd;
pd->file = EINA_FALSE;
pd->win32 = NULL;
_handler_reset(obj, pd);
}
static int
_efl_loop_handler_fd_get(Eo *obj EINA_UNUSED, Efl_Loop_Handler_Data *pd)
{
if (pd->win32) return -1;
return pd->file ? -1 : pd->fd;
}
static void
_efl_loop_handler_fd_file_set(Eo *obj, Efl_Loop_Handler_Data *pd, int fd)
{
pd->fd = fd;
pd->file = EINA_TRUE;
pd->win32 = NULL;
_handler_reset(obj, pd);
}
static int
_efl_loop_handler_fd_file_get(Eo *obj EINA_UNUSED, Efl_Loop_Handler_Data *pd)
{
if (pd->win32) return -1;
return pd->file ? pd->fd : -1;
}
static void
_efl_loop_handler_win32_set(Eo *obj, Efl_Loop_Handler_Data *pd, void *handle)
{
pd->fd = -1;
pd->file = EINA_FALSE;
pd->win32 = handle;
_handler_reset(obj, pd);
}
static void *
_efl_loop_handler_win32_get(Eo *obj EINA_UNUSED, Efl_Loop_Handler_Data *pd)
{
return pd->win32;
}
static void
_efl_loop_handler_efl_object_parent_set(Eo *obj, Efl_Loop_Handler_Data *pd, Efl_Object *parent)
{
efl_parent_set(efl_super(obj, MY_CLASS), parent);
if ((!pd->constructed) || (!pd->finalized)) return;
_handler_clear(pd);
if (pd->loop)
{
pd->loop_data->fd_handlers_obj = eina_list_remove
(pd->loop_data->fd_handlers_obj, obj);
pd->loop = NULL;
pd->loop_data = NULL;
}
if (parent == NULL) return;
pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS);
pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS);
if (pd->loop_data)
pd->loop_data->fd_handlers_obj =
eina_list_append(pd->loop_data->fd_handlers_obj, obj);
_handler_reset(obj, pd);
}
static Efl_Object *
_efl_loop_handler_efl_object_constructor(Eo *obj, Efl_Loop_Handler_Data *pd)
{
efl_constructor(efl_super(obj, MY_CLASS));
efl_event_callback_array_add(obj, _event_callback_watch(), pd);
pd->constructed = EINA_TRUE;
return obj;
}
static Efl_Object *
_efl_loop_handler_efl_object_finalize(Eo *obj, Efl_Loop_Handler_Data *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_data)
pd->loop_data->fd_handlers_obj =
eina_list_append(pd->loop_data->fd_handlers_obj, obj);
pd->finalized = EINA_TRUE;
_handler_reset(obj, pd);
return efl_finalize(efl_super(obj, MY_CLASS));
}
static void
_efl_loop_handler_efl_object_destructor(Eo *obj, Efl_Loop_Handler_Data *pd)
{
efl_destructor(efl_super(obj, MY_CLASS));
if (pd->loop_data)
pd->loop_data->fd_handlers_obj =
eina_list_remove(pd->loop_data->fd_handlers_obj, obj);
_handler_clear(pd);
}
#include "efl_loop_handler.eo.c"

View File

@ -0,0 +1,72 @@
import eina_types;
enum Efl.Loop.Handler.Flags {
[[ A set of flags that can be OR'd together to indicate which are
desired ]]
none = 0, [[ No I/O is desired (generally useless) ]]
read = 1, [[ Reading is desired ]]
write = 2, [[ Writing is desired ]]
error = 4, [[ Error channel input is desired ]]
}
class Efl.Loop.Handler (Efl.Object)
{
[[ An object that describes an low-level source of I/O to listen to
for available data to be read or written, depending on the OS and data
source type. When I/O becomes available various events are produced
and the callbacks attached to them will be called. ]]
methods {
@property active {
[[ This sets what kind of I/O should be listened to only when
using a fd or fd_file for the handler ]]
set { }
get { }
values {
flags: Efl.Loop.Handler.Flags; [[ The flags that indicate what kind of I/O should be listened for like read, write or error channels. ]]
}
}
@property fd {
[[ Controls a file desciptor to listen to for I/O that points
to a data pipe such as a device, socket or pipe etc. ]]
set { }
get { }
values {
fd: int; [[ The file descriptor ]]
}
}
@property fd_file {
[[ Controls a file descriptor to listen to for I/O that
specifically points to a file in storage and not a device, socket or
pipe etc. ]]
set { }
get { }
values {
fd: int; [[ The file descriptor ]]
}
}
@property win32 {
[[ Controls a windows win32 object handle to listen to for I/O.
When it becomes available for any data the read event will be
produced. ]]
set { }
get { }
values {
handle: void_ptr; [[ A win32 object handle ]]
}
}
}
events {
read; [[ Called when a read happened on the descriptor ]]
write; [[ Called when a write happened on the descriptor ]]
error; [[ Called when a error occurred on the descriptor ]]
buffer; [[ Called when buffered data already read from the descriptor should be processed ]]
prepare; [[ Called when preparing a descriptor for listening ]]
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
Efl.Object.finalize;
Efl.Object.parent { set; }
}
}

View File

@ -0,0 +1,83 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include "Ecore.h"
#include "ecore_private.h"
#define MY_CLASS EFL_LOOP_MESSAGE_CLASS
#include "ecore_main_common.h"
typedef struct _Efl_Loop_Message_Data Efl_Loop_Message_Data;
struct _Efl_Loop_Message_Data
{
Eina_Inlist *send_list_node;
Eo *loop;
Efl_Loop_Data *loop_data;
};
/////////////////////////////////////////////////////////////////////////////
void
_efl_loop_message_send_info_set(Eo *obj, Eina_Inlist *node, Eo *loop, Efl_Loop_Data *loop_data)
{
Efl_Loop_Message_Data *pd = efl_data_scope_get(obj, MY_CLASS);
if (!pd) return;
pd->send_list_node = node;
pd->loop = loop;
pd->loop_data = loop_data;
}
void
_efl_loop_message_unsend(Eo *obj)
{
Efl_Loop_Message_Data *pd = efl_data_scope_get(obj, MY_CLASS);
if (!pd) return;
if ((!pd->send_list_node) || (!pd->loop)) return;
Message *msg = (Message *)pd->send_list_node;
msg->delete_me = EINA_TRUE;
}
/////////////////////////////////////////////////////////////////////////////
EOLIAN static Efl_Object *
_efl_loop_message_efl_object_constructor(Eo *obj, Efl_Loop_Message_Data *pd EINA_UNUSED)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
return obj;
}
EOLIAN static void
_efl_loop_message_efl_object_destructor(Eo *obj, Efl_Loop_Message_Data *pd)
{
if ((pd->send_list_node) && (pd->loop_data))
{
Message *msg = (Message *)pd->send_list_node;
msg->delete_me = EINA_TRUE;
msg->message = NULL;
msg->handler = NULL;
if (pd->loop_data->message_walking == 0)
{
pd->loop_data->message_queue =
eina_inlist_remove(pd->loop_data->message_queue,
pd->send_list_node);
}
pd->send_list_node = NULL;
pd->loop = NULL;
pd->loop_data = NULL;
free(pd->send_list_node);
}
efl_destructor(efl_super(obj, MY_CLASS));
}
#include "efl_loop_message.eo.c"

View File

@ -0,0 +1,13 @@
import efl_types;
import eina_types;
class Efl.Loop.Message (Efl.Object)
{
[[ ]]
methods {
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
}
}

View File

@ -0,0 +1,145 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include "Ecore.h"
#include "ecore_private.h"
#define MY_CLASS EFL_LOOP_MESSAGE_HANDLER_CLASS
#include "ecore_main_common.h"
typedef struct _Efl_Loop_Message_Handler_Data Efl_Loop_Message_Handler_Data;
struct _Efl_Loop_Message_Handler_Data
{
Eo *loop;
Efl_Loop_Data *loop_data;
};
EOLIAN static Efl_Loop_Message *
_efl_loop_message_handler_message_add(Eo *obj, Efl_Loop_Message_Handler_Data *pd EINA_UNUSED)
{
// XXX: implement message object cache
Efl_Loop_Message *message = efl_add(EFL_LOOP_MESSAGE_CLASS, obj);
if (!message) return NULL;
// XXX: track added messages not sent yet ...
return message;
}
EOLIAN static void
_efl_loop_message_handler_message_send(Eo *obj, Efl_Loop_Message_Handler_Data *pd, Efl_Loop_Message *message)
{
Message *msg;
if (EINA_UNLIKELY(!pd->loop))
{
pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS);
if (!pd->loop) return;
pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS);
if (!pd->loop_data)
{
pd->loop = NULL;
return;
}
}
msg = calloc(1, sizeof(Message));
if (msg)
{
msg->handler = obj;
msg->message = message;
pd->loop_data->message_queue = eina_inlist_append
(pd->loop_data->message_queue, EINA_INLIST_GET(msg));
_efl_loop_message_send_info_set(message, EINA_INLIST_GET(msg),
pd->loop, pd->loop_data);
return;
}
efl_del(message);
}
EOLIAN static void
_efl_loop_message_handler_message_call(Eo *obj, Efl_Loop_Message_Handler_Data *pd, Efl_Loop_Message *message)
{
Message *msg;
unsigned int n = 0;
Eina_Bool found = EINA_FALSE;
if (!pd->loop) return;
EINA_INLIST_FOREACH(pd->loop_data->message_queue, msg)
{
n++;
if (msg->message != message) continue;
found = EINA_TRUE;
msg->message = NULL;
msg->handler = NULL;
_efl_loop_message_send_info_set(message, NULL, NULL, NULL);
if ((pd->loop_data->message_walking == 0) || (n == 1))
{
pd->loop_data->message_queue =
eina_inlist_remove(pd->loop_data->message_queue,
EINA_INLIST_GET(msg));
free(msg);
}
else
msg->delete_me = EINA_TRUE;
break;
}
efl_event_callback_call(obj, EFL_LOOP_MESSAGE_HANDLER_EVENT_MESSAGE,
message);
// XXX: implement message object cache...
if (message) efl_del(message);
if (found) return;
ERR("Cannot find message called object %p on message queue", message);
}
EOLIAN static Eina_Bool
_efl_loop_message_handler_message_clear(Eo *obj, Efl_Loop_Message_Handler_Data *pd)
{
Eina_Inlist *tmp;
Message *msg;
if (!pd->loop) return EINA_FALSE;
if (!pd->loop_data->message_queue) return EINA_FALSE;
EINA_INLIST_FOREACH_SAFE(pd->loop_data->message_queue, tmp, msg)
{
if (msg->handler == obj)
{
Eo *message = msg->message;
msg->delete_me = EINA_TRUE;
msg->handler = NULL;
msg->message = NULL;
_efl_loop_message_send_info_set(message, NULL, NULL, NULL);
if (pd->loop_data->message_walking == 0)
{
pd->loop_data->message_queue =
eina_inlist_remove(pd->loop_data->message_queue,
EINA_INLIST_GET(msg));
free(msg);
}
if (message) efl_del(message);
}
}
return EINA_FALSE;
}
EOLIAN static Efl_Object *
_efl_loop_message_handler_efl_object_constructor(Eo *obj, Efl_Loop_Message_Handler_Data *pd EINA_UNUSED)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
return obj;
}
EOLIAN static void
_efl_loop_message_handler_efl_object_destructor(Eo *obj, Efl_Loop_Message_Handler_Data *pd EINA_UNUSED)
{
efl_destructor(efl_super(obj, MY_CLASS));
}
#include "efl_loop_message_handler.eo.c"

View File

@ -0,0 +1,38 @@
import efl_types;
import eina_types;
class Efl.Loop.Message.Handler (Efl.Object)
{
[[ ]]
methods {
message_add {
[[ ]]
return: Efl.Loop.Message; [[ ]]
}
message_send {
[[ Plase the message on the queue to be called later ]]
params {
@in message: Efl.Loop.Message; [[ ]]
}
}
message_call {
[[ Overide me (implement) then call super after calling the
right callback type if you specialize the message type
]]
params {
@in message: Efl.Loop.Message; [[ Generic message event type ]]
}
}
message_clear {
[[ ]]
return: bool; [[ ]]
}
}
events {
message: Efl.Loop.Message; [[ ]]
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
}
}

View File

@ -21,6 +21,8 @@ struct _Efl_Promise_Msg
struct _Efl_Promise_Data
{
Eo *loop;
Efl_Loop_Data *loop_data;
Efl_Promise *promise;
Efl_Promise_Msg *message;
Eina_List *futures;
@ -589,7 +591,6 @@ void
ecore_loop_promise_fulfill(Eo *obj)
{
Efl_Promise_Data *pd = efl_data_scope_get(obj, EFL_PROMISE_CLASS);
_efl_promise_propagate(obj, pd);
}
@ -675,16 +676,8 @@ _efl_promise_progress_set(Eo *obj, Efl_Promise_Data *pd, const void *p)
}
}
static Efl_Object *
_efl_promise_efl_object_constructor(Eo *obj, Efl_Promise_Data *pd)
{
pd->promise = obj;
return efl_constructor(efl_super(obj, EFL_PROMISE_CLASS));
}
static void
_efl_promise_efl_object_destructor(Eo *obj, Efl_Promise_Data *pd)
_efl_promise_loop_clear(Eo *obj, Efl_Promise_Data *pd)
{
pd->nodelay = EINA_TRUE;
@ -698,7 +691,7 @@ _efl_promise_efl_object_destructor(Eo *obj, Efl_Promise_Data *pd)
if (pd->message &&
!pd->propagated)
{
ecore_loop_promise_unregister(efl_provider_find(obj, EFL_LOOP_CLASS), obj);
ecore_loop_promise_unregister(pd->loop, obj);
_efl_promise_propagate(obj, pd);
}
@ -708,7 +701,28 @@ _efl_promise_efl_object_destructor(Eo *obj, Efl_Promise_Data *pd)
_efl_promise_msg_free(pd->message);
pd->message = NULL;
}
}
static void
_efl_promise_efl_object_parent_set(Eo *obj, Efl_Promise_Data *pd, Efl_Object *parent)
{
if (!parent) _efl_promise_loop_clear(obj, pd);
efl_parent_set(efl_super(obj, EFL_PROMISE_CLASS), parent);
pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS);
pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS);
}
static Efl_Object *
_efl_promise_efl_object_constructor(Eo *obj, Efl_Promise_Data *pd)
{
pd->promise = obj;
return efl_constructor(efl_super(obj, EFL_PROMISE_CLASS));
}
static void
_efl_promise_efl_object_destructor(Eo *obj, Efl_Promise_Data *pd)
{
_efl_promise_loop_clear(obj, pd);
efl_destructor(efl_super(obj, EFL_PROMISE_CLASS));
}

View File

@ -73,5 +73,6 @@ class Efl.Promise (Efl.Loop.Consumer)
implements {
Efl.Object.destructor;
Efl.Object.constructor;
Efl.Object.parent { set; }
}
}